1 | /**
|
2 | * A [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)
|
3 | * in-place - which means that it **will change the order of the original
|
4 | * array by reference**.
|
5 | *
|
6 | * This is an algorithm that generates a random [permutation](https://en.wikipedia.org/wiki/Permutation)
|
7 | * of a set.
|
8 | *
|
9 | * @param {Array} x sample of one or more numbers
|
10 | * @param {Function} [randomSource=Math.random] an optional entropy source that
|
11 | * returns numbers between 0 inclusive and 1 exclusive: the range [0, 1)
|
12 | * @returns {Array} x
|
13 | * @example
|
14 | * var x = [1, 2, 3, 4];
|
15 | * shuffleInPlace(x);
|
16 | * // x is shuffled to a value like [2, 1, 4, 3]
|
17 | */
|
18 | function shuffleInPlace(x, randomSource) {
|
19 | // a custom random number source can be provided if you want to use
|
20 | // a fixed seed or another random number generator, like
|
21 | // [random-js](https://www.npmjs.org/package/random-js)
|
22 | randomSource = randomSource || Math.random;
|
23 |
|
24 | // store the current length of the x to determine
|
25 | // when no elements remain to shuffle.
|
26 | let length = x.length;
|
27 |
|
28 | // temporary is used to hold an item when it is being
|
29 | // swapped between indices.
|
30 | let temporary;
|
31 |
|
32 | // The index to swap at each stage.
|
33 | let index;
|
34 |
|
35 | // While there are still items to shuffle
|
36 | while (length > 0) {
|
37 | // chose a random index within the subset of the array
|
38 | // that is not yet shuffled
|
39 | index = Math.floor(randomSource() * length--);
|
40 |
|
41 | // store the value that we'll move temporarily
|
42 | temporary = x[length];
|
43 |
|
44 | // swap the value at `x[length]` with `x[index]`
|
45 | x[length] = x[index];
|
46 | x[index] = temporary;
|
47 | }
|
48 |
|
49 | return x;
|
50 | }
|
51 |
|
52 | export default shuffleInPlace;
|