aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Puc <marcin.e.puc@gmail.com>2021-03-12 18:39:22 +0100
committerLouis Pilfold <louis@lpil.uk>2021-03-20 13:35:54 +0000
commitf97bc1a39a588c775d44dd4baedce3e1ac2414f5 (patch)
treec5948b657a0dde8f67c5bd10ed163d0376475e3c
parent5072b0e961add30e0a03df5e9b8d1d6f455f7085 (diff)
downloadgleam_stdlib-f97bc1a39a588c775d44dd4baedce3e1ac2414f5.tar.gz
gleam_stdlib-f97bc1a39a588c775d44dd4baedce3e1ac2414f5.zip
Add list.chunk_by
-rw-r--r--src/gleam/list.gleam39
-rw-r--r--test/gleam/list_test.gleam6
2 files changed, 45 insertions, 0 deletions
diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam
index 1f430ad..9572e36 100644
--- a/src/gleam/list.gleam
+++ b/src/gleam/list.gleam
@@ -1269,3 +1269,42 @@ pub fn take_while(
) -> List(a) {
do_take_while(list, predicate, [])
}
+
+fn do_chunk_by(
+ list: List(a),
+ f: fn(a) -> key,
+ previous_key: key,
+ current_chunk: List(a),
+ acc: List(List(a)),
+) -> List(List(a)) {
+ case list {
+ [] ->
+ case current_chunk {
+ [] -> reverse(acc)
+ remaining -> reverse([reverse(remaining), ..acc])
+ }
+ [head, ..tail] -> {
+ let key = f(head)
+ case key == previous_key {
+ False ->
+ do_chunk_by(tail, f, key, [head], [reverse(current_chunk), ..acc])
+ True -> do_chunk_by(tail, f, key, [head, ..current_chunk], acc)
+ }
+ }
+ }
+}
+
+/// Returns a list of chunks in which
+/// the result of calling `f` on each element is the same.
+///
+/// ## Examples
+///
+/// > [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk_by(fn(n) { n % 2 })
+/// [[1], [2, 2], [3], [4, 4, 6], [7, 7]]
+///
+pub fn chunk_by(in list: List(a), with f: fn(a) -> key) -> List(List(a)) {
+ case list {
+ [] -> []
+ [head, ..tail] -> do_chunk_by(tail, f, f(head), [head], [])
+ }
+}
diff --git a/test/gleam/list_test.gleam b/test/gleam/list_test.gleam
index abeafdf..091bd96 100644
--- a/test/gleam/list_test.gleam
+++ b/test/gleam/list_test.gleam
@@ -590,3 +590,9 @@ pub fn take_while_test() {
|> list.take_while(fn(x) { x < 3 })
|> should.equal([1, 2])
}
+
+pub fn chunk_by_test() {
+ [1, 2, 2, 3, 4, 4, 6, 7, 7]
+ |> list.chunk_by(fn(n) { n % 2 })
+ |> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7]])
+}