2

I want to know how to shuffle an array and return a NEW array. So far I have seen this solution in Stack Overflow:

How to randomize (shuffle) a JavaScript array?

This solution works perfectly in returning the same array shuffled, but I don't really understand why. Can anyone explain this and help me revise it so that it returns a new array?

Thanks!

Community
  • 1
  • 1
lnamba
  • 1,681
  • 3
  • 18
  • 26

4 Answers4

4

The easiest way I know of to create a copy of an array is using:

var newArray = [].concat(originalArray);

You could perform that in the first line of most of the solutions on the linked answer and you would be getting a new array back with the original untouched. Here is a modified version of the top rated answer on the linked question:

function shuffle(originalArray) {
  var array = [].concat(originalArray);
  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.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}
Rob M.
  • 35,491
  • 6
  • 51
  • 50
  • 1
    [Clone Arrays with JavaScript](https://davidwalsh.name/javascript-clone-array) suggests `var array = originalArray.slice(0);`. – Ouroborus Mar 23 '17 at 01:08
  • @Ouroborus yes that is another way of cloning arrays. I don't think you should modify the `Array` prototype though, as he suggests. Also, `concat` appears to be significantly faster than `slice`: https://jsperf.com/test-slice-vs-concat/1 – Rob M. Mar 23 '17 at 01:17
  • 1
    Actually, it's only significantly faster in Chrome, in Safari they are about equal and Firefox `slice` is significantly faster. Oh browsers... :P – Rob M. Mar 23 '17 at 01:19
  • Great thank you Rob! That seemed so simple, so I think I was just making it more complicated than it was. Thanks again! – lnamba Mar 23 '17 at 01:32
3

Maybe useful for you

var original = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var copy = [].concat(original);
copy.sort(function(){
  return 0.5 - Math.random();
});
console.log(copy);
Valentin Podkamennyi
  • 7,161
  • 4
  • 29
  • 44
dipenparmar12
  • 3,042
  • 1
  • 29
  • 39
0

If you want to use 3rd party library, Lodash is very good for this.

Just use _.shuffle(), to get new array.

Ouroborus
  • 16,237
  • 4
  • 39
  • 62
raju
  • 6,448
  • 24
  • 80
  • 163
0

const shuffle = (array) => {
  const mutatedArray = [...array];

  for (let i = mutatedArray.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [mutatedArray[i], mutatedArray[j]] = [mutatedArray[j], mutatedArray[i]];
  }

  return mutatedArray;
};
console.log(shuffle(["a", "b", "c", "d"]))

Powered by Fisher-Yates algorithm.

iPiranhaa
  • 11
  • 2