Randomly shuffle the order of an array in JavaScript?

Answered
coderguy asked this question 1 year, 7 months ago
coderguy on Feb 18, 2022

How can I take a given array of strings and randomly shuffle the index positions of each string?

For example, an array of strings like this:

["string1", "string2", "string3", "string4", "string5"]

Should be randomly shuffled into this:

["string3", "string5", "string1", "string4", "string2"]
8 suggested answers
nick on Mar 24, 2022

Here's a function you can use. It's based on the Fisher-Yates (aka Knuth) Shuffle.

const shuffle = function(array) {
  let currentIndex = array.length,  randomIndex;

  // Only run while there are still items to shuffle
  while (currentIndex != 0) {

    // Pick a remaining element
    randomIndex = Math.floor(Math.random() * currentIndex);

    // Decrement the currentIndex value
    currentIndex--;

    // Swap it with the current element
    [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
  }

  return array;
}

It's used like this:

shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

// [10, 1, 8, 6, 3, 2, 4, 7, 9, 5]
0 replies
rusty1_rusty1 on Mar 24, 2022

You can do this using a combination of map() and sort():

const originalArray = ["string1", "string2", "string3", "string4", "string5"]

const shuffledArray = originalArray
  .map(value => ({ value, sort: Math.random() }))
  .sort((a, b) => a.sort - b.sort)
  .map(({ value }) => value)
  1. Put each array item into an object and assign it a random sort key.
  2. Sort the items based on the random key.
  3. Remove each item from the object.

This is a good method for short to medium length arrays. If you are dealing with large arrays, this method may not be optimal in terms of performance.

This is an implementation of the Schwartzian Transform.

0 replies
moon_man41 on Mar 24, 2022

The Underscore library has the shuffle method:

_.shuffle(["string1", "string2", "string3", "string4", "string5"])

This will shuffle your array in place and return the new array. It uses the Fisher-Yates (aka Knuth) Shuffle method.

0 replies
softwareguy411 on Mar 24, 2022

Durstenfeld Shuffle method for you:

function shuffleArray(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));

    [arr[i], arr[j]] = [arr[j], arr[i]];
  }

  return arr
}

shuffleArray(["string1", "string2", "string3", "string4", "string5"])

// [ "string5", "string3", "string2", "string4", "string1" ]

It picks a random item from the array and removes it from the next draw. Much like picking a random card from a deck cards would work.

0 replies
yaboy01 on Mar 24, 2022
function shuffle(array) {
  let count = array.length, randomnumber, temp;

  while (count){
    randomnumber = Math.random() * count-- | 0;
    temp = array[count];
    array[count] = array[randomnumber];
    array[randomnumber] = temp
  }

  return array
}
0 replies
suparman21 on Mar 24, 2022

Another function you could use:

function shuffle(array) {
  for (var i = array.length - 1; i > 0; i--) {
      var j = Math.floor(Math.random() * (i + 1));
      var temp = array[i];
      array[i] = array[j];
      array[j] = temp;
  }

  return array
}

It's an implementation of the Durstenfeld Shuffle.

0 replies
itsbambi on Mar 24, 2022

Here's a recursive solution that should work for you:

const shuffleArray = (array) => {
  if (array.length === 1) return array;

  const randomNum = Math.floor(Math.random() * array.length);

  return [array[randomNum], ...shuffleArray(array.filter((_, i) => i != randomNum))];
};
0 replies
timmy123 on Mar 24, 2022
function shuffle(array) {
  return [...array].map((_, i, newArray) => {
    var random = i + (Math.floor( Math.random() * (newArray.length - i)));

    [newArray[random], newArray[i]] = [newArray[i], newArray[random]]

    return newArray[i]
  })
}
0 replies
Answered