@@ -16,40 +16,64 @@ import scala.collection.immutable.ArraySeq
16
16
import scala .jdk .CollectionConverters ._
17
17
import scala .reflect .ClassTag
18
18
19
- class TraversalSugarExt [A ](val iterator : Iterator [A ]) extends AnyVal {
19
+ class TraversalSugarExt [A ](val iter : Iterator [A ]) extends AnyVal {
20
20
type Traversal [A ] = Iterator [A ]
21
21
22
22
/** Execute the traversal and convert the result to a list - shorthand for `toList` */
23
23
@ Doc (info = " Execute the traversal and convert the result to a list - shorthand for `toList`" )
24
- def l : List [A ] = iterator.toList
24
+ def l : List [A ] = iter.toList
25
+
26
+ /** group elements and count how often they appear */
27
+ @ Doc (info = " group elements and count how often they appear" )
28
+ def groupCount [B >: A ]: Map [B , Int ] =
29
+ groupCount(identity[A ])
30
+
31
+ /** group elements by a given transformation function and count how often the results appear */
32
+ @ Doc (info = " group elements by a given transformation function and count how often the results appear" )
33
+ def groupCount [B ](by : A => B ): Map [B , Int ] = {
34
+ val counts = mutable.Map .empty[B , Int ].withDefaultValue(0 )
35
+ iter.foreach { a =>
36
+ val b = by(a)
37
+ val newValue = counts(b) + 1
38
+ counts.update(b, newValue)
39
+ }
40
+ counts.to(Map )
41
+ }
42
+
43
+ def groupBy [K ](f : A => K ): Map [K , List [A ]] = l.groupBy(f)
44
+ def groupMap [K , B ](key : A => K )(f : A => B ): Map [K , List [B ]] = l.groupMap(key)(f)
45
+ def groupMapReduce [K , B ](key : A => K )(f : A => B )(reduce : (B , B ) => B ): Map [K , B ] = l.groupMapReduce(key)(f)(reduce)
46
+
47
+ /** Execute the traversal and return a mutable.Set (better performance than `immutableSet` and has stable iterator
48
+ * order)
49
+ */
50
+ def toSetMutable [B >: A ]: mutable.LinkedHashSet [B ] = mutable.LinkedHashSet .from(iter)
25
51
26
- /** Execute the traversal and return a mutable.Set (better performance than `immutableSet`) */
27
- def toSetMutable [B >: A ]: mutable.Set [B ] = mutable.Set .from(iterator)
52
+ /** Execute the traversal and convert the result to an immutable Set. */
28
53
29
- /** Execute the traversal and convert the result to an immutable Set */
30
- def toSetImmutable [B >: A ]: Set [B ] = iterator.toSet
54
+ def toSetImmutable [B >: A ]: Set [B ] = iter.toSet
31
55
32
56
/** Execute the traversal without returning anything */
33
57
@ Doc (info = " Execute the traversal without returning anything" )
34
58
def iterate (): Unit =
35
- while (iterator .hasNext) iterator .next()
59
+ while (iter .hasNext) iter .next()
36
60
37
61
def countTrav : Traversal [Int ] =
38
- Iterator .single(iterator .size)
62
+ Iterator .single(iter .size)
39
63
40
- def head : A = iterator .next()
64
+ def head : A = iter .next()
41
65
42
- def headOption : Option [A ] = iterator .nextOption()
66
+ def headOption : Option [A ] = iter .nextOption()
43
67
44
68
def last : A = {
45
- iterator .hasNext
46
- var res = iterator .next()
47
- while (iterator .hasNext) res = iterator .next()
69
+ iter .hasNext
70
+ var res = iter .next()
71
+ while (iter .hasNext) res = iter .next()
48
72
res
49
73
}
50
74
51
75
def lastOption : Option [A ] =
52
- if (iterator .hasNext) Some (last) else None
76
+ if (iter .hasNext) Some (last) else None
53
77
54
78
/** casts all elements to given type note: this can lead to casting errors
55
79
*
@@ -58,33 +82,33 @@ class TraversalSugarExt[A](val iterator: Iterator[A]) extends AnyVal {
58
82
*/
59
83
@ Doc (info = " casts all elements to given type" )
60
84
def cast [B ]: Traversal [B ] =
61
- iterator .asInstanceOf [Traversal [B ]]
85
+ iter .asInstanceOf [Traversal [B ]]
62
86
63
87
/** collects all elements of the given class (beware of type-erasure) */
64
88
@ Doc (info = " collects all elements of the provided class (beware of type-erasure)" )
65
89
def collectAll [B ](implicit ev : ClassTag [B ]): Traversal [B ] =
66
- iterator .filter(ev.runtimeClass.isInstance).asInstanceOf [Traversal [B ]]
90
+ iter .filter(ev.runtimeClass.isInstance).asInstanceOf [Traversal [B ]]
67
91
68
92
/** Deduplicate elements of this traversal - a.k.a. distinct, unique, ... */
69
93
@ Doc (info = " deduplicate elements of this traversal - a.k.a. distinct, unique, ..." )
70
94
def dedup : Traversal [A ] =
71
- iterator .distinct
95
+ iter .distinct
72
96
73
97
/** deduplicate elements of this traversal by a given function */
74
98
@ Doc (info = " deduplicate elements of this traversal by a given function" )
75
99
def dedupBy (fun : A => Any ): Traversal [A ] =
76
- iterator .distinctBy(fun)
100
+ iter .distinctBy(fun)
77
101
78
102
/** sort elements by their natural order */
79
103
@ Doc (info = " sort elements by their natural order" )
80
104
def sorted [B >: A ](implicit ord : Ordering [B ]): Seq [B ] = {
81
- (iterator .to(ArraySeq .untagged): ArraySeq [B ]).sorted
105
+ (iter .to(ArraySeq .untagged): ArraySeq [B ]).sorted
82
106
}
83
107
84
108
/** sort elements by the value of the given transformation function */
85
109
@ Doc (info = " sort elements by the value of the given transformation function" )
86
110
def sortBy [B ](f : A => B )(implicit ord : Ordering [B ]): Seq [A ] =
87
- iterator .to(ArraySeq .untagged).sortBy(f)
111
+ iter .to(ArraySeq .untagged).sortBy(f)
88
112
89
113
/** Print help/documentation based on the current elementType `A`. Relies on all step extensions being annotated with
90
114
* \@Traversal / @Doc Note that this works independently of tab completion and implicit conversions in scope - it
0 commit comments