-1

I know that there is already question for "how to shuffle an array in JavaScript" but I didn't find a specific question for how to shuffle an array immutably. So, what's the best way to shuffle an array immutably in JavaScript?

Maybe taking the answer from https://stackoverflow.com/a/2450976/3022127 and simply copying the array first (inside of the method) would be the best way?

Or maybe something like this:

const shuffleArray = (arr) => {
  return arr
    .map(a => [Math.random(), a])
    .sort((a, b) => a[0] - b[0])
    .map(a => a[1])
}

(seems to be pretty random https://jsfiddle.net/Lpy22x4c/1/)

bersling
  • 17,851
  • 9
  • 60
  • 74
  • 6
    What do you mean by "shuffle an array immutably"? Do you mean without modifying the original array? Just make a copy of the array and shuffle that. – Barmar Apr 26 '18 at 07:18

2 Answers2

1

Copying the array first and then shuffling in place makes good sense, yes.

Alternately, the implementation in the question you linked can easily be adjusted to create a new array, leaving the old array unmodified. The primary change is getting the element for currentIndex: We want to get it from the new array if the new array has it, the old array if not.

function shuffle(array) {
  var newArray = [];
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

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

    // And swap it with the current element.
    if (newArray.hasOwnProperty(currentIndex)) {
      temporaryValue = newArray[currentIndex];
    } else {
      temporaryValue = array[currentIndex];
    }
    newArray[currentIndex] = array[randomIndex];
    newArray[randomIndex] = temporaryValue;
  }

  return newArray;
}

// Used like so
var arr = [2, 11, 37, 42];
console.log("shuffled", shuffle(arr));
console.log("original", arr);
.as-console-wrapper {
  max-height: 100% !important;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
-1

Just use this solution but set a new variable equal to your array before you do the shuffling: How can I shuffle an array?

So it would look like:

 /**
 * Shuffles array in place.
 * @param {Array} a items An array containing the items.
 */
function shuffle(oldArray) {
  var j, x, i;
  var newArray = oldArray;
  for (i = newArray.length - 1; i > 0; i--) {
    j = Math.floor(Math.random() * (i + 1));
    x = newArray[i];
    newArray[i] = newArray[j];
    newArray[j] = x;
   }
   return newArray;
  } 
Bill Gryta
  • 11
  • 1