Skip to content

Commit 6c9a956

Browse files
authored
add list.shuffle (#360)
1 parent e640192 commit 6c9a956

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- Fixed a bug where `regex.scan` would not work correctly on utf8.
1212
- The performance of `list.flatten` has been greatly improved.
1313
- The `string_builder` module gains the `join` function.
14+
- The `list` module gains the `shuffle` function.
1415

1516
## v0.24.0 - 2022-10-15
1617

src/gleam/list.gleam

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
////
2424

2525
import gleam/int
26+
import gleam/float
2627
import gleam/order.{Order}
2728
import gleam/pair
2829

@@ -1822,3 +1823,44 @@ pub fn transpose(list_of_list: List(List(a))) -> List(List(a)) {
18221823
}
18231824
}
18241825
}
1826+
1827+
fn do_shuffle_pair_unwrap(list: List(#(Float, a)), acc: List(a)) -> List(a) {
1828+
case list {
1829+
[] -> acc
1830+
_ -> {
1831+
let [elem_pair, ..enumerable] = list
1832+
do_shuffle_pair_unwrap(enumerable, [elem_pair.1, ..acc])
1833+
}
1834+
}
1835+
}
1836+
1837+
fn do_shuffle_by_pair_indexes(
1838+
list_of_pairs: List(#(Float, a)),
1839+
) -> List(#(Float, a)) {
1840+
sort(
1841+
list_of_pairs,
1842+
fn(a_pair: #(Float, a), b_pair: #(Float, a)) -> Order {
1843+
float.compare(a_pair.0, b_pair.0)
1844+
},
1845+
)
1846+
}
1847+
1848+
/// Takes a list, randomly sorts all items and returns the shuffled list.
1849+
///
1850+
/// ## Example
1851+
///
1852+
/// ```gleam
1853+
/// list.range(1, 10)
1854+
/// |> list.shuffle()
1855+
/// > [1, 6, 9, 10, 3, 8, 4, 2, 7, 5]
1856+
/// ```
1857+
///
1858+
/// Notice: This function uses Erlang's `:rand` module or Javascript's
1859+
/// `Math.random()` to calcuate the index shuffling.
1860+
///
1861+
pub fn shuffle(list: List(a)) -> List(a) {
1862+
list
1863+
|> fold(from: [], with: fn(acc, a) { [#(float.random(0.0, 1.0), a), ..acc] })
1864+
|> do_shuffle_by_pair_indexes()
1865+
|> do_shuffle_pair_unwrap([])
1866+
}

test/gleam/list_test.gleam

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,3 +1081,26 @@ pub fn transpose_test() {
10811081
list.transpose([[1, 2, 3], [101, 102], [201, 202, 203]])
10821082
|> should.equal([[1, 101, 201], [2, 102, 202], [3, 203]])
10831083
}
1084+
1085+
pub fn shuffle_test() {
1086+
[]
1087+
|> list.shuffle
1088+
|> should.equal([])
1089+
1090+
[1, 1]
1091+
|> list.shuffle
1092+
|> should.equal([1, 1])
1093+
1094+
[1, 1, 1]
1095+
|> list.shuffle
1096+
|> should.equal([1, 1, 1])
1097+
1098+
list.range(1, 100)
1099+
|> list.shuffle
1100+
|> list.sort(int.compare)
1101+
|> should.equal(list.range(1, 100))
1102+
1103+
// TCO test
1104+
list.range(0, recursion_test_cycles)
1105+
|> list.shuffle()
1106+
}

0 commit comments

Comments
 (0)