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.

An image of cards being prepared to be shuffled

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.



Feel free to check out my work here: