1313package scala .collection
1414package next
1515
16+ import scala .language .implicitConversions
17+
1618private [next] final class NextIterableOnceOpsExtensions [A , CC [_], C ](
1719 private val col : IterableOnceOps [A , CC , C ]
1820) extends AnyVal {
21+ import NextIterableOnceOpsExtensions .GroupMap
22+
1923 /**
2024 * Partitions this IterableOnce into a map according to a discriminator function `key`. All the values that
2125 * have the same discriminator are then transformed by the `value` function and then reduced into a
@@ -28,14 +32,70 @@ private[next] final class NextIterableOnceOpsExtensions[A, CC[_], C](
2832 *
2933 * @note This will force the evaluation of the Iterator.
3034 */
31- def groupMapReduce [K , B ](key : A => K )(f : A => B )(reduce : (B , B ) => B ): immutable.Map [K , B ] = {
32- val m = mutable.Map .empty[K , B ]
33- col.foreach { elem =>
34- m.updateWith(key = key(elem)) {
35- case Some (b) => Some (reduce(b, f(elem)))
36- case None => Some (f(elem))
35+ def groupMapReduce [K , B ](key : A => K )(f : A => B )(reduce : (B , B ) => B ): immutable.Map [K , B ] =
36+ groupMapTo(key)(f).reduce(reduce)
37+
38+ def groupByTo [K ](key : A => K ): GroupMap [A , K , A , immutable.Iterable , immutable.Map ] =
39+ groupMapTo(key)(identity)
40+
41+ def groupMapTo [K , V ](key : A => K )(f : A => V ): GroupMap [A , K , V , immutable.Iterable , immutable.Map ] =
42+ new GroupMap (col, key, f, immutable.Iterable , immutable.Map )
43+ }
44+
45+ object NextIterableOnceOpsExtensions {
46+ final case class GroupMap [A , K , V , CC [_], MC [_, _]](
47+ col : IterableOnceOps [A , Any , Any ],
48+ key : A => K ,
49+ f : A => V ,
50+ colFactory : Factory [V , CC [V ]],
51+ mapFactory : CustomMapFactory [MC , K ]
52+ ) {
53+ def collectValuesAs [CC1 [_]](factory : Factory [V , CC1 [V ]]): GroupMap [A , K , V , CC1 , MC ] =
54+ this .copy(colFactory = factory)
55+
56+ def collectResultsAs [MC1 [_, _]](factory : CustomMapFactory [MC1 , K ]): GroupMap [A , K , V , CC , MC1 ] =
57+ this .copy(mapFactory = factory)
58+
59+ final def result : MC [K , CC [V ]] = {
60+ val m = mutable.Map .empty[K , mutable.Builder [V , CC [V ]]]
61+ col.foreach { elem =>
62+ val k = key(elem)
63+ val v = f(elem)
64+ m.get(k) match {
65+ case Some (builder) => builder.addOne(v)
66+ case None => m += (k -> colFactory.newBuilder.addOne(v))
67+ }
68+ }
69+ mapFactory.from(m.view.mapValues(_.result()))
70+ }
71+
72+ final def reduce (reduce : (V , V ) => V ): MC [K , V ] = {
73+ val m = mutable.Map .empty[K , V ]
74+ col.foreach { elem =>
75+ m.updateWith(key = key(elem)) {
76+ case Some (b) => Some (reduce(b, f(elem)))
77+ case None => Some (f(elem))
78+ }
3779 }
80+ mapFactory.from(m)
3881 }
39- m.to(immutable.Map )
82+ }
83+
84+ sealed trait CustomMapFactory [MC [_, _], K ] {
85+ def from [V ](col : IterableOnce [(K , V )]): MC [K , V ]
86+ }
87+
88+ object CustomMapFactory {
89+ implicit def fromMapFactory [MC [_, _], K ](mf : MapFactory [MC ]): CustomMapFactory [MC , K ] =
90+ new CustomMapFactory [MC , K ] {
91+ override def from [V ](col : IterableOnce [(K , V )]): MC [K , V ] =
92+ mf.from(col)
93+ }
94+
95+ implicit def fromSortedMapFactory [MC [_, _], K : Ordering ](smf : SortedMapFactory [MC ]): CustomMapFactory [MC , K ] =
96+ new CustomMapFactory [MC , K ] {
97+ override def from [V ](col : IterableOnce [(K , V )]): MC [K , V ] =
98+ smf.from(col)
99+ }
40100 }
41101}
0 commit comments