aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/gleam/list.gleam45
-rw-r--r--test/gleam/list_test.gleam30
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]])
+}