Randomize the order of members in a JavaScript array
Also known as ''shuffling an array'', we'll use a simple array to see how we can randomly reorder its members
By: Ajdin Imsirovic 08 January 2021
The most popular approach to randomizing arrays is known as Fischer Yates, and if we must shuffle a large array, that’s what we should use. However, it’s a bit advanced, so it won’t be too helpful for learning.
Instead, we’ll look at a simple implementation using the familiar map()
and sort()
methods.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(function() {
const orderedFruits = [
'apple',
'banana',
'cherry',
'durian',
'elderberry',
'fig',
'grape'
];
const unorderedFruits = [];
for(let i = 0; i < orderedFruits.length; i++) {
unorderedFruits.push(
orderedFruits[
Math.floor(Math.random() * orderedFruits.length)
]
)
}
console.log(unorderedFruits)
})()
It might seem this is all it takes, but actually, the logged out unorderedFruits
array will sometimes show us that our implementation is not perfect. Here are a few outputs of our code:
1
2
(7) ["grape", "cherry", "banana", "elderberry", "fig", "apple", "durian"]
(7) ["durian", "durian", "cherry", "elderberry", "durian", "fig", "cherry"]
Since Math.random() * orderedFruits.length
will sometimes return the same number, and in that case, we’d be pushing the same member of the original array into the unorderedFruits
array.
To fix this problem, we’ll use the splice()
method. Additionally, we’ll have to count our array down, not up:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(function() {
const orderedFruits = [
'apple',
'banana',
'cherry',
'durian',
'elderberry',
'fig',
'grape'
];
const unorderedFruits = [];
for(let i = orderedFruits.length-1; i >= 0; i--) {
let unorderedItem =
orderedFruits.splice(
Math.floor(
Math.random() * orderedFruits.length), 1
);
unorderedFruits.push(unorderedItem);
}
console.log(unorderedFruits)
})()
With the above code, we get an array of seven arrays, with each nested array holding a single member:
1
(7) [Array(1), Array(1), Array(1), Array(1), Array(1), Array(1), Array(1)]
In other words, we get this:
1
2
3
4
5
6
7
8
9
[
0: ["grape"]
1: ["fig"]
2: ["durian"]
3: ["elderberry"]
4: ["apple"]
5: ["banana"]
6: ["cherry"]
]
Now, all we need to do now is flatten this array into a single array without nesting. For that, we’ll use the Array.prototype.flat()
method.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(function() {
const orderedFruits = [
'apple',
'banana',
'cherry',
'durian',
'elderberry',
'fig',
'grape'
];
const unorderedFruits = [];
for(let i = orderedFruits.length-1; i >= 0; i--) {
let unorderedItem =
orderedFruits.splice(
Math.floor(
Math.random() * orderedFruits.length), 1
);
unorderedFruits.push(unorderedItem);
}
unorderedFruits = unorderedFruits.flat();
console.log(unorderedFruits)
})()
To avoid the error Uncaught TypeError: Assignment to constant variable.
, we’ll change the const
to let
on unorderedFruits
variable declaration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(function() {
const orderedFruits = [
'apple',
'banana',
'cherry',
'durian',
'elderberry',
'fig',
'grape'
];
let unorderedFruits = [];
for(let i = orderedFruits.length-1; i >= 0; i--) {
let unorderedItem =
orderedFruits.splice(
Math.floor(
Math.random() * orderedFruits.length), 1
);
unorderedFruits.push(unorderedItem);
}
unorderedFruits = unorderedFruits.flat();
console.log(unorderedFruits)
})()
Here’s the result of running it a few times:
1
2
3
4
(7) ["fig", "cherry", "banana", "grape", "apple", "elderberry", "durian"]
(7) ["grape", "banana", "apple", "durian", "elderberry", "fig", "cherry"]
(7) ["grape", "elderberry", "banana", "durian", "fig", "apple", "cherry"]
(7) ["elderberry", "grape", "apple", "banana", "fig", "durian", "cherry"]
Note:
This exercise comes from Book 3
of my book series on JS, available on Leanpub.com.