13
13
package scala .collection
14
14
package next
15
15
16
+ import scala .language .implicitConversions
17
+
16
18
private [next] final class NextIterableOnceOpsExtensions [A , CC [_], C ](
17
19
private val col : IterableOnceOps [A , CC , C ]
18
20
) extends AnyVal {
21
+ import NextIterableOnceOpsExtensions .GroupMap
22
+
19
23
/**
20
24
* Partitions this IterableOnce into a map according to a discriminator function `key`. All the values that
21
25
* 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](
28
32
*
29
33
* @note This will force the evaluation of the Iterator.
30
34
*/
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
+ }
37
79
}
80
+ mapFactory.from(m)
38
81
}
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
+ }
40
100
}
41
101
}
0 commit comments