Explain Codes LogoExplain Codes Logo

How can I shuffle an array?

javascript
shuffle
array
performance
Anton ShumikhinbyAnton Shumikhin·Oct 2, 2024
TLDR

To shuffle an array in JavaScript, use the Fisher-Yates algorithm:

/** * This function would make a deck of cards sweat in nervous anticipation. * Fisher–Yates Shuffle: for when you absolutely must confound your arrays. */ function shuffle(arr) { let newArr = [...arr]; for (let i = newArr.length - 1; i > 0; i--) { let j = Math.floor(Math.random() * (i + 1)); [newArr[i], newArr[j]] = [newArr[j], newArr[i]]; // ✨ array destructuring magic ✨ } return newArr; }

Invoke the shuffle function on your array, and voilà—unpredictable chaos.

Understanding the shuffle

The ES6 shuffle: be concise, pay the price

Here's the ES6 version:

/** * Hipster level: over 9000. * Revel in conciseness at potentially the cost of performance. */ const shuffle = (arr) => { const newArr = [...arr]; for (let i = newArr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [newArr[i], newArr[j]] = [newArr[j], newArr[i]]; } return newArr; };

The destructuring and arrow function make the code more succinct but it might have a performance hit with large arrays due to spread operator.

Why Fisher-Yates is your best night out ever

  • Efficiency in numbers: O(n) time complexity. Good news for big party arrays.
  • Reliability: Ensures everyone has an equal chance to get to any position — all about fairness!
  • True randomness: Because predictable parties don't make for good stories.

Add shuffle as array prototype—mind the gap

Put protective coding into play:

if (!Array.prototype.safeShuffle) { Array.prototype.safeShuffle = function() { return shuffle(this); }; }

Your arrays can now be shuffled without being harmed. But remember, with great power comes great responsibility - avoid frequent prototype modification.

Pass the randomness check

Ensuring the shuffle really is as random as your playlist:

  • Statistical tests: Run multiple shuffles and examine that results distribution.
  • Visualization tests: A good shuffle doesn't show patterns.
  • Code audit: Good old-fashioned peer review never hurts.

Danger: watch your steps

Guard against empty or non-array inputs

Don't let innocent calls to your function cause a breakdown:

if (!Array.isArray(arr) || !arr.length) return [];

The deceptive lure of sort() with Math.random()

The tempting but flawed approach:

arr.sort(() => 0.5 - Math.random()); // ❌ Bad news!

This creates a bias, favouring certain elements—kind of like always giving the biggest piece of cake to your favourite sibling.

The case for in place shuffle

The non-destructive shuffle is often ideal, but in-place shuffling can be necessary, especially when dealing with:

  • Memory Limitations: When your assembly is too large, like fitting an opera house into a pub!
  • Performance: In-place shuffling is quicker than producing a marching band out of thin air.

But be aware, modifying the original array can lead to bugs faster than a picnic attracts ants.