Skip to main content

JavaScript: Shuffling Array Elements

Clown bloke

Shuffle is different than random in term. But indeed randomness is applied in shuffling.

As in shuffling cards and giving out one random card, those are different.

Algorithmically, we can loop through the reference array, generate random index based on the reference array length, then put that item (with that random index) to a new array.

But since random can generate similar number (being floored or rounded down) as previous one, that can lead to duplicates.

For example

We have an array:

Then loop through it while blindly creating a random index to copy the randomly chosen item to a new array, surely there will be duplicates.

Unwanted output:


Deletion

We need to trim the array reference after one element gets picked by the random index.

Example array input:

Then we want to shuffle the array input.

  • Create a clone of the original array (clonedArray), so that nothing will happen to the original one.

    Then create an empty array (bufferArray) to store the shuffled elements.

  • Loop through the clonedArray to randomly pick an element from it, then place that chosen element to bufferArray. Then delete/remove that particular element from the clonedArray.

    For instance this is the initial clonedArray:

    First loop, it generates random index of 1.

    That means the element "b" (index 1) is picked from the clonedArray.

    Then we put that picked element to the bufferArray then delete that element from clonedArray.

    And after that, the loop continues, we get another random index as 1, no problem, because the clonedArray is different now.

    So, the next picked element (with index 1) from ["a", "c", "d"] is "c".

    Now we have:

    And so on.

    As you can see in that looping sequence, the clonedArray length will decrease until it's empty, and the bufferArray length will increase and it will have the shuffled items.


Code

This is my original code back in 2015 (first published) with minor adjustment of camel casing the variable names and default function parameter (arr = []).

The original array, with the variable arr, will be left intact.

That shuffle function above can be cascaded, like so:

To shuffle the original array four times.


Using do-while, while, and forEach

Each of those will behave similarly as the first code snippet.


Fisher-Yates BOSS Technique

This technique is the most efficient, introduced by Richard Durstenfeld in 1964. This is the description at Wikipedia.

Let's take the snippet from Wikipedia:

The technique is straightforward, without introducing mutation to the clonedArray or any other computation. Get random index, then swap, BAM!

But as you can see above, the snippet doesn't return anything. It's just snippet of the technique.

This is the proper vibe.

That is actually EFFICIENT! 😲 🥳

It generates similar to the prior concept, but with peak efficiency.

The problem with pure randomness, the shuffled array can have similar sequence.

At some point, this input:

Can be shuffled as:

We want to ensure the generated sequence always differs from the original input.

We can add if condition within the loop, and we need while to accomplish it, as such:

I implement while so that there is no extra overhead inside the loop. I am only interested in simple boolean check within the loop.

The function shuffleItReal above will act as efficient as fisherYatesShuffle, but with addition that it will always generate different sequence than the reference array.


Benchmark

Let's make a default array with 10,000 items, invoke each technique 1,000 times, and measure the completion duration of it.

This is the snapshot of the results:

Benchmark result
Technique comparison

And this is the BOSS technique + same sequence avoidance.

Last modified on

Comments