JS Tip: How to Shuffle An Array in JavaScript

Hi there, today I will be sharing a tip on shuffling an array in JavaScript. The algorithm we will come up with can actually be implemented in any programming language but I will be doing it in JavaScript.

Input

Say we are given an array of a primitive type in JavaScript e.g [1, 3, 4, 5, 6, 2] or ["Tom", "Jerry", "Parker", "Wick"]

Output

The output is an array that contains the same elements as the first array but the order of those elements have been randomized

Where might we need this? I had to use this algorithm when working on an 8-Puzzle Game in JavaScript, I wrote a tutorial on how to replicate the game here.

Approach

What we want to achieve is to put each element in the array in a random place other than where it was initially. So we can implement the algorithm by looping through the array, each time we encounter an element, we compute a random position and swap it with the element at that position.

Here is a code snippet that works:

// input array
const arr = [1, 3, 4, 5, 2, 5]

for(let i = 0; i < arr.length; i++) {
  // generate a random integer less than arr.length
  let randomPosition = parseInt(Math.random()*arr.length);

  // swap current element with element at randomPosition
   let temp = arr[i];
   arr[i] = arr[randomPosition];
   arr[randomPosition] = temp;
}
console.log(arr)

Math.random() returns a random number between 0 (inclusive), and 1 (exclusive). I multiple the random number generated by arr.length and then convert it to an integer so that we can have an integer less than arr.length.

This code surely works but we can improve it.

Improvement

One thing we are doing in the snippet above is that we are changing the original input array, it's not advisable to mutate input especially when it's not explicit that the input will be mutated. What we will do is make a copy of the array before shuffling it, so it's the copy that will be mutated.

Also, we don't need to loop through the whole array to shuffle it. The current implementation will move some elements twice, it's enough to loop through only half of the array.

Here is the code snippet with those improvements:

const arr = [1, 3, 4, 5, 2, 5]
const arrCopy = [...arr]


for(let i = 0; i < arrCopy.length/2; i++) {
  // generate a random integer less than arr.length
  let randomPosition = parseInt(Math.random()*arr.length);

  // swap current element with element at randomPosition
   let temp = arrCopy[i];
   arrCopy[i] = arrCopy[randomPosition];
   arrCopy[randomPosition] = temp;
}
console.log("Original array (unchanged): ", arr)
console.log("Shuffled copy of array: ",arrCopy)

Modularizing For Reuse

Now we have an algorithm that works and we are good with that. But the code that shuffles is in global scope, it would be better to write it in a function. Also, the code snippet that swaps elements can go into a function too.

// returns a shuffled array
function shuffleArray(arr) {
  const arrCopy = [...arr]

  for(let i = 0; i < arrCopy.length/2; i++) {
  // generate a random integer less than arr.length
  let randomPosition = parseInt(Math.random()*arr.length);

  // swap current element with element at randomPosition
  swap(arrCopy, i, randomPosition)
  }
  return arrCopy
}


// Swaps array elements at the provide indices
function swap(inputArray, index1, index2) {
  let temp = inputArray[index1];
  inputArray[index1] = inputArray[index2];
  inputArray[index2] = temp;
}

const arr = [1, 3, 4, 5, 2, 5]
console.log(shuffleArray(arr))

Note that the swap function mutates the inputArray, in this case, this is the desired behavior.

Conclusion

I hope you have learned a thing or two in this article, let me know if you find it helpful below in the comments. And if you spot any bug, kindly let me know.

You can find the code in this article on JsBin here.

Happy Coding.