diff options
author | Sebastian Porto <s@porto5.com> | 2021-05-06 19:18:51 +1000 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2021-05-11 10:28:03 +0100 |
commit | 931d4544510afa4d879ef6c5e52f4750d0812f45 (patch) | |
tree | 4cd6527c49c953af011eda91481ca1901e59e56f | |
parent | 8efb599e9e97c856f7e3d9c60b5b4cf9df6a1fe0 (diff) | |
download | gleam_stdlib-931d4544510afa4d879ef6c5e52f4750d0812f45.tar.gz gleam_stdlib-931d4544510afa4d879ef6c5e52f4750d0812f45.zip |
Add list.transpose and list.interleave
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | src/gleam/list.gleam | 45 | ||||
-rw-r--r-- | test/gleam/list_test.gleam | 30 |
3 files changed, 76 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index db088af..b169239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- The `list` module gains the `flat_map` function. +- The `list` module gains the `interleave`, `flat_map` and `transpose` functions. - The `option` module gains the `all` and `values` functions. - The `result` module gains the `values` function. - All modules now use the new `#(a, b, ...)` tuple syntax. diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam index a0b3b16..1e29ff3 100644 --- a/src/gleam/list.gleam +++ b/src/gleam/list.gleam @@ -1522,3 +1522,48 @@ pub fn combination_pairs(items: List(a)) -> List(#(a, a)) { do_combination_pairs(items) |> flatten } + +/// Make a list alternating the elements from the given lists +/// +/// ## Examples +/// +/// ``` +/// > list.interleave([[1, 2], [101, 102], [201, 202]]) +/// [1, 101, 201, 2, 102, 202] +/// ``` +/// +pub fn interleave(list: List(List(a))) -> List(a) { + transpose(list) + |> flatten +} + +/// Transpose rows and columns of the list of lists. +/// +/// ## Examples +/// +/// ``` +/// > transpose([[1, 2, 3], [101, 102, 103]]) +/// [[1, 101], [2, 102], [3, 103]] +/// ``` +pub fn transpose(list_of_list: List(List(a))) -> List(List(a)) { + let take_first = fn(list) { + case list { + [] -> [] + [f] -> [f] + [f, .._rest] -> [f] + } + } + + case list_of_list { + [] -> [] + [[], ..xss] -> transpose(xss) + rows -> { + let firsts = + rows + |> map(take_first) + |> flatten + let rest = transpose(map(rows, drop(_, 1))) + [firsts, ..rest] + } + } +} diff --git a/test/gleam/list_test.gleam b/test/gleam/list_test.gleam index c7e2a34..c4f5ea3 100644 --- a/test/gleam/list_test.gleam +++ b/test/gleam/list_test.gleam @@ -692,3 +692,33 @@ pub fn combination_pairs_test() { list.combination_pairs([1, 2, 3, 4]) |> should.equal([#(1, 2), #(1, 3), #(1, 4), #(2, 3), #(2, 4), #(3, 4)]) } + +pub fn interleave_test() { + list.interleave([[1, 2], [101, 102]]) + |> should.equal([1, 101, 2, 102]) + + list.interleave([[1, 2], [101, 102], [201, 202]]) + |> should.equal([1, 101, 201, 2, 102, 202]) + + // Left over elements are added at the end + list.interleave([[1, 2, 3], [101, 102]]) + |> should.equal([1, 101, 2, 102, 3]) + + list.interleave([[1, 2], [101, 102, 103]]) + |> should.equal([1, 101, 2, 102, 103]) +} + +pub fn transpose_test() { + list.transpose([[1, 2, 3], [101, 102, 103]]) + |> should.equal([[1, 101], [2, 102], [3, 103]]) + + list.transpose([[1, 2, 3], [101, 102, 103], [201, 202, 203]]) + |> should.equal([[1, 101, 201], [2, 102, 202], [3, 103, 203]]) + + // Left over elements are still returned + list.transpose([[1, 2], [101, 102, 103]]) + |> should.equal([[1, 101], [2, 102], [103]]) + + list.transpose([[1, 2, 3], [101, 102], [201, 202, 203]]) + |> should.equal([[1, 101, 201], [2, 102, 202], [3, 203]]) +} |