ここに私が見つけることができる最も簡単な実装があります(それは一般的で面倒です):
/** takes 'it' and groups consecutive elements
* until next item that satisfy 'startGroup' predicate occures.
* It returns Iterator[List[T]] and is lazy
* (keeps in memory only last group, not whole 'it').
*/
def groupUsing[T](it:Iterator[T])(startGroup:T => Boolean):Iterator[List[T]] = {
val sc = it.scanLeft(List.empty[T]) {
(a,b) => if (startGroup(b)) b::Nil else b::a
}
(sc ++ Iterator(Nil)).sliding(2,1).collect {
case Seq(a,b) if a.length >= b.length => a.reverse
}
}
そのように使用してください:
val exampleIt = Seq("H1","D1","D2","D3","H2","D4","H3","H4","D5","D6","H5","D7").toIterator
groupUsing(exampleIt)(_.startsWith("H"))
// H1 D1 D2 D3 / H2 D4 / H3 / H4 D5 D6 / H5 D7
これが仕様です:
X | GIVEN | EXPECTED |
O | | | empty iterator
O | H | H | single header
O | D | D | single item (not header)
O | HD | HD |
O | HH | H,H | only headers
O | HHD | H,HD |
O | HDDDHD | HDDD,HD |
O | DDH | DD,H | heading D's have no Header as you can see.
O | HDDDHDHDD | HDDD,HD,HDD |
テストと追加コメントを含むscalafiddle:
https
(回答が役に立った場合は賛成投票してください。少し時間をかけすぎました:))
2番目の実装:
使用しない バージョンを提案していますsliding
。ここにありますが、以下に示す独自の問題があります。
def groupUsing2[T >: Null](it:Iterator[T])(startGroup:T => Boolean):Iterator[List[T]] = {
type TT = (List[T], List[T])
val empty:TT = (Nil, Nil)
//We need this ugly `++ Iterator(null)` to close last group.
val sc = (it ++ Iterator(null)).scanLeft(empty) {
(a,b) => if (b == null || startGroup(b)) (b::Nil, a._1) else (b::a._1, Nil)
}
sc.collect {
case (_, a) if a.nonEmpty => a.reverse
}
}
特徴:
- (-)のみ機能します
T>:Null
タイプます。最後のコレクションを最後に閉じる要素を追加するだけです(nullは完璧ですが、タイプが制限されます)。
- (〜)以前のバージョンと同じ量のtrshを作成する必要があります。2番目のタプルではなく、最初のステップでタプルを作成するだけです。
- (+)リストの長さをチェックしません(これは正直に言うと大きな利益です)。
- (+)コアでは、Ivan Kurchenkoの回答ですが、余分なボクシングはありません。
これがscalafiddleです:https ://scalafiddle.io/sf/q8xbQ9N/11