Last modified: Jul 31, 2026

How to Shuffle a JavaScript Array Randomly

Shuffling an array is a common task in JavaScript. You might need it for games, quizzes, or randomizing data. A good shuffle must be fair. It should give every possible order an equal chance.

Many beginners use a simple trick with sort(). But that method is often biased. In this guide, we will explore the best ways to shuffle arrays. We will focus on the popular Fisher-Yates algorithm for perfect randomness.

Why Avoid Using sort() with Math.random()?

A common shortcut looks like this: array.sort(() => Math.random() - 0.5). It is short and easy to remember. However, it does not produce a truly random shuffle.

The problem is that the comparison function is inconsistent. The sort algorithm expects a consistent order. When the random values change each time, the result is biased. Some elements will appear more often at certain positions.

For small arrays, it might look fine. But for larger arrays, the bias becomes clear. It is not a reliable method. Let's look at a better solution.

The Fisher-Yates Shuffle Algorithm

The Fisher-Yates algorithm is the gold standard. It is efficient and produces an unbiased shuffle. It works by iterating from the last element to the first. For each position, it picks a random index from the unshuffled part and swaps them.

This algorithm runs in O(n) time. It is also in-place, meaning it modifies the original array. This makes it fast and memory-efficient. Let's see how to implement it.


// Fisher-Yates Shuffle Implementation
function shuffleArray(array) {
  // Loop from the last index down to 1
  for (let i = array.length - 1; i > 0; i--) {
    // Pick a random index from 0 to i (inclusive)
    const j = Math.floor(Math.random() * (i + 1));
    
    // Swap elements at positions i and j
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

// Example usage
const myArray = [1, 2, 3, 4, 5];
const shuffled = shuffleArray(myArray);
console.log(shuffled);

// Possible Output:
[ 3, 1, 5, 2, 4 ]

In the code above, we use array destructuring to swap elements. This is a clean way to do it. The loop runs from the end to the beginning. This ensures each element has an equal chance to end up anywhere.

This method is robust and fast. It is the recommended approach for almost all cases. If you need to shuffle an array, use this algorithm.

Shuffling Without Modifying the Original Array

The Fisher-Yates algorithm we wrote modifies the original array. Sometimes, you want to keep the original data. You can create a copy first and then shuffle the copy.

Use the spread operator or slice() to make a copy. Then pass the copy to the shuffle function. This way, the original array stays intact.


function shuffleArrayCopy(array) {
  // Create a copy of the original array
  const copy = [...array];
  
  // Apply Fisher-Yates to the copy
  for (let i = copy.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [copy[i], copy[j]] = [copy[j], copy[i]];
  }
  return copy;
}

const original = ['a', 'b', 'c', 'd'];
const shuffledCopy = shuffleArrayCopy(original);

console.log('Original:', original);
console.log('Shuffled:', shuffledCopy);

// Output:
Original: [ 'a', 'b', 'c', 'd' ]
Shuffled: [ 'c', 'a', 'd', 'b' ]

This approach is very useful. It gives you flexibility. You can keep the original order for reference. This is often needed in data processing tasks. If you work with complex data, understanding arrays of objects is helpful.

Using a Library (Lodash)

If you are using a utility library like Lodash, it has a built-in shuffle function. It is based on the Fisher-Yates algorithm. It is tested and reliable.

To use it, you need to install Lodash first. Then you can import the shuffle function. It works on both arrays and strings.


// Using Lodash (assuming it is installed)
const _ = require('lodash');

const numbers = [10, 20, 30, 40, 50];
const shuffledNumbers = _.shuffle(numbers);

console.log(shuffledNumbers);

// Output:
[ 40, 10, 30, 50, 20 ]

Using a library can save time. It is well-tested and handles edge cases. However, for a simple task, writing your own function is fine. It helps you understand the logic better.

Practical Use Cases for Shuffling

Shuffling is useful in many real-world scenarios. Here are a few examples. You can use it to randomize quiz questions. You can also use it to create a random playlist.

Another common use is in card games. You need to shuffle the deck before dealing. Shuffling is also used in machine learning to mix training data. This helps avoid bias in the model.

When working with multiple arrays, you might need to shuffle them in sync. This means the same indices should be paired after the shuffle. You can do this by shuffling an array of indices first. Then, map the original arrays based on the shuffled indices.

This technique is a bit more advanced. It shows the power of array manipulation. If you want to learn more about handling arrays, check out this guide on array methods.

Testing the Randomness of Your Shuffle

It is hard to test randomness just by looking. A good way is to run the shuffle many times. Then, count how often each element appears in each position. For a fair shuffle, the counts should be roughly equal.

You can perform a simple statistical test. This is not a formal proof, but it can catch obvious bugs. Run the shuffle 10,000 times on a small array. Then, check the frequency of each element at each index.


// Simple frequency test
function testShuffle() {
  const results = [[0,0,0], [0,0,0], [0,0,0]];
  const array = [1, 2, 3];

  for (let i = 0; i < 10000; i++) {
    const shuffled = shuffleArray([...array]);
    for (let j = 0; j < shuffled.length; j++) {
      results[shuffled[j] - 1][j]++;
    }
  }
  console.log(results);
}

testShuffle();

// Sample Output (counts will vary slightly):
[ [ 1654, 1689, 1657 ],
  [ 1666, 1654, 1680 ],
  [ 1680, 1657, 1663 ] ]

In the output, each row represents an element (1, 2, 3). Each column represents a position (0, 1, 2). The counts are close to 3333, which is expected. This gives confidence that the shuffle is unbiased.

Handling Edge Cases

What about empty arrays or arrays with one element? The Fisher-Yates algorithm handles them perfectly. The loop will not run, and the array will be returned as is. This is the correct behavior.

What about arrays with non-numeric elements? The algorithm works on any type of element. It only swaps values based on indices. It does not care about the actual data.

This makes it very versatile. You can shuffle arrays of strings, objects, or even nested arrays. If you have nested arrays, you might want to look at this guide on arrays of arrays.

Performance Considerations

The Fisher-Yates algorithm is very fast. It runs in O(n) time. This means it scales linearly with the array size. Even for large arrays, it is quick.

The space complexity is O(1) for the in-place version. This is excellent. It does not create extra large copies of the array. This is important for memory-constrained environments.

If you are working with huge datasets, this efficiency matters. It is one of the reasons why this algorithm is so popular. There is no need to overcomplicate things.

For simpler array transformations, you might also be interested in the reduce method. It is powerful for other tasks.

Conclusion

Shuffling an array randomly is a fundamental skill in JavaScript. The best way is to use the Fisher-Yates algorithm. It is efficient, unbiased, and easy to implement. Avoid using sort() with random for this purpose.

We covered the main implementation. We also looked at how to shuffle without modifying the original array. We saw a library alternative with Lodash. We also discussed testing and edge cases.

Now you can confidently shuffle arrays in your projects. Use the code examples as a reference. Practice with different types of arrays. This will help you master this important concept.