aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcin Puc <marcin.e.puc@gmail.com>2021-03-14 23:38:49 +0100
committerLouis Pilfold <louis@lpil.uk>2021-04-06 20:45:48 +0100
commit8d83506941b16722aed6eab102565bfd163ba053 (patch)
treee0165523ac4eb7989414257c151ecf693a8784fb /src
parent0bd24c71d631e0a7dc915c3bea91d7d68ae9ac41 (diff)
downloadgleam_stdlib-8d83506941b16722aed6eab102565bfd163ba053.tar.gz
gleam_stdlib-8d83506941b16722aed6eab102565bfd163ba053.zip
Add iterator.group
Diffstat (limited to 'src')
-rw-r--r--src/gleam/iterator.gleam40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam
index 4ea19f6..f9e39bb 100644
--- a/src/gleam/iterator.gleam
+++ b/src/gleam/iterator.gleam
@@ -1,4 +1,5 @@
import gleam/list
+import gleam/map.{Map}
// Internal private representation of an Iterator
type Action(element) {
@@ -879,3 +880,42 @@ pub fn all(
iterator.continuation
|> do_all(predicate)
}
+
+fn update_group_with(
+ el: element,
+) -> fn(Result(List(element), Nil)) -> List(element) {
+ fn(maybe_group) {
+ case maybe_group {
+ Ok(group) -> [el, ..group]
+ Error(Nil) -> [el]
+ }
+ }
+}
+
+fn group_updater(
+ f: fn(element) -> key,
+) -> fn(element, Map(key, List(element))) -> Map(key, List(element)) {
+ fn(elem, groups) {
+ groups
+ |> map.update(f(elem), update_group_with(elem))
+ }
+}
+
+/// Returns a `Map(k, List(element))` of elements from the given iterator
+/// grouped with the given key function.
+///
+/// The order within each group is preserved from the iterator.
+///
+/// ## Examples
+///
+/// > from_list([1, 2, 3, 4, 5, 6]) |> group(by: fn(n) { n % 3 })
+/// map.from_list([tuple(0, [3, 6]), tuple(1, [1, 4]), tuple(2, [2, 5])])
+///
+pub fn group(
+ in iterator: Iterator(element),
+ by key: fn(element) -> key,
+) -> Map(key, List(element)) {
+ iterator
+ |> fold(map.new(), group_updater(key))
+ |> map.map_values(fn(_, group) { list.reverse(group) })
+}