Skip to content

Commit f20b817

Browse files
committed
Import splitWith from strawman-contrib
Taken from: https://github.com/scala/collection-strawman/issues/241
1 parent 2837fdb commit f20b817

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

src/main/scala/scala/collection/decorators/SeqDecorator.scala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,49 @@ class SeqDecorator[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) {
4141
def intersperse[B >: seq.A, That](start: B, sep: B, end: B)(implicit bf: BuildFrom[C, B, That]): That =
4242
bf.fromSpecificIterable(coll)(new View.IntersperseSurround(seq(coll), start, sep, end))
4343

44+
/** Splits this collection into groups according to the given predicate.
45+
*
46+
* @param p the predicate used to discriminate elements
47+
* @return A nested collection with groups of elements,
48+
* opening new groups whenever the predicate
49+
* changes the return type
50+
*
51+
* @example {{{
52+
* // Example 1: Split a list of integers into groups that are even / odd
53+
* List(1, 2, 4, 6, 7).splitWith(i => i % 2 == 0) => List(List(1), List(2, 4, 6), List(7))
54+
*
55+
* // Example 2: Split a list of chars into groups that are upper case or lower case
56+
* List('a', 'b', 'C', 'D', 'e', 'f').splitWith(_.isUpper) => List(List('a', 'b'), List('C', 'D'), List('e', 'f'))
57+
* }}}
58+
*/
59+
def splitWith[That](p: seq.A => Boolean)(implicit bf: BuildFrom[C, seq.A, That]): That = {
60+
def newGroupBuilder() = seq().iterableFactory.newBuilder[seq.A]
61+
62+
//TODO: How to get a builder of a nested target collection?
63+
val groups: mutable.Builder[seq.A, That] = bf.newBuilder(coll)
64+
val it: Iterator[seq.A] = seq(coll).iterator
65+
66+
var currentGroup = newGroupBuilder()
67+
var lastTestResult = Option.empty[Boolean]
68+
69+
while (it.hasNext) {
70+
val elem = it.next()
71+
val currentTest = p(elem)
72+
73+
lastTestResult match {
74+
case None =>
75+
currentGroup.addOne(elem)
76+
case Some(lastTest) if currentTest == lastTest =>
77+
currentGroup.addOne(elem)
78+
case Some(_) =>
79+
groups.addOne(currentGroup.result())
80+
currentGroup = newGroupBuilder().addOne(elem)
81+
}
82+
83+
lastTestResult = Some(currentTest)
84+
}
85+
86+
groups.addOne(currentGroup.result()).result()
87+
}
88+
4489
}

0 commit comments

Comments
 (0)