I have an array like this:

var arr1 = ["a", "b", "c", "d"];

How can I randomize / shuffle it?

10 upvote
  flag
6 upvote
  flag
Just throwing this here that you can visualize how random a shuffle function actually is with this visualizer Mike Bostock made: bost.ocks.org/mike/shuffle/compare.html – aug
3 upvote
  flag
@Blazemonger jsPref is dead. Can you just post here which is the fastest? – 3zzy
upvote
  flag
I added an answer that can be concatenated and doesn't extend the native Array prototype. – Francisco Presencia
upvote
  flag
What about a one-liner? The returned array is shuffled. arr1.reduce((a,v)=>a.splice(Math.floor(Math.random() * a.length), 0, v) && a, []) – brunettdan

35 Answers 11

up vote 964 down vote accepted

The de-facto unbiased shuffle algorithm is the Fisher-Yates (aka Knuth) Shuffle.

See https://github.com/coolaj86/knuth-shuffle

You can see a great visualization here (and the original post linked to this)

function shuffle(array) {
  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;
}

// Used like so
var arr = [2, 11, 37, 42];
arr = shuffle(arr);
console.log(arr);

Some more info about the algorithm used.

upvote
  flag
... except that Math.random() is not random at all, and therefore the Fisher-Yates Shuffle will not randomly shuffle for sufficiently large sets. Just pointing this out in case someone attempts to the latter. – nikola
upvote
  flag
@prometheus , what do you mean math.random is not random? why is it called math.random if it isnt? – Click Upvote
4 upvote
  flag
Here's a CoffeeScript implementation of the Fisher-Yates algorithm: gist.github.com/859699 – Derek Dahmer
11 upvote
  flag
The above answer skips element 0, the condition should be i-- not --i. Also, the test if (i==0)... is superfluous since if i == 0 the while loop will never be entered. The call to Math.floor can be done faster using ...| 0. Either tempi or tempj can be removed and the value be directly assigned to myArray[i] or j as appropriate. – RobG
20 upvote
  flag
@prometheus, all RNGs are pseudo-random unless connected to expensive hardware. – Phil H
1 upvote
  flag
Is @RobG right? Why don't you post another answer, RobG, instead of commenting this one. – jm.
1 upvote
  flag
@jm—About skipping zero? In the test while (--i) then if i = 1 when the loop starts, it will first be decremented to zero before being tested. The test will return false and so the loop isn't executed when i == 0. As for returning false if length is zero, that makes no sense at all - shuffling an empty array should just return the empty array. Another answer? There a zillion articles on the web about shuffling. – RobG
upvote
  flag
Oh, a good resource for shuffl, deal and draw is http://www.merlyn.demon.co.uk/js-shufl.htm – RobG
29 upvote
  flag
@RobG the implementation above is functionally correct. In the Fisher-Yates algorithm, the loop isn't meant to run for the first element in the array. Check out wikipedia where there are other implementations that also skip the first element. Also check out this article which talks about why it is important for the loop not to run for the first element. – theon
upvote
  flag
@RobG, @jm, Math.random() returns a number 0<=n<1. So after flooring Math.random() * ( 0 + 1 ) you'll always be swapping the first element with itself. – joeytwiddle
upvote
  flag
@joeytwiddle—|0 is just a different way to floor the value, happy with theon's explanation of why the first item should be skipped. – RobG
upvote
  flag
Bad to give a particular implementation - should use one from a library. – frabcus
20 upvote
  flag
@nikola "not random at all" is a little strong a qualification for me. I would argue that it is sufficiently random unless you're a cryptographer, in which case you're probably not using Math.Random() in the first place. – toon81
upvote
  flag
Another good read for ensuring your algorithm is on point. cigital.com/papers/download/developer_gambling.php – theGrayFox
3 upvote
  flag
Anyone who is going to use this implementation: DO NOT forget that this will CHANGE the given array! This will NOT create a new one and return a new array!.. – scaryguy
upvote
  flag
@theon This returns duplicate results? Is my understanding wrong? – xameeramir
3 upvote
  flag
@student It is a random shuffle. For an array with 4 elements, there are only 24 permutations. So for a given shuffle, another shuffle has a 1 in 24 chance of being the same. After 25 shuffles you are guaranteed to have at least one pair of duplicate results. – theon
upvote
  flag
@nikola Remember, the importance of random number generation is too important to leave to chance. – JonathanHayward
upvote
  flag
Does anyone know the inside-out version of this? en.wikipedia.org/wiki/… – Michelle
upvote
  flag
Why arr = shuffle(arr); and not just shuffle(arr);? The array is passed in by reference so you can just keep the original reference. – JoeRocc
3 upvote
  flag
Ugh, yoda (0 !== currentIndex). – ffxsam
upvote
  flag
This would be faster with Math.random() * currentIndex | 0 – gman
upvote
  flag
If you don't want to modify the old array, add var clone = array.slice(0); on the first line and then return the clone array instead. – sonlexqt

One could (or should) use it as a protoype from Array:

From ChristopheD:

Array.prototype.shuffle = function() {
  var i = this.length, j, temp;
  if ( i == 0 ) return this;
  while ( --i ) {
     j = Math.floor( Math.random() * ( i + 1 ) );
     temp = this[i];
     this[i] = this[j];
     this[j] = temp;
  }
  return this;
}
15 upvote
  flag
+1 for using prototype... – user1589754
24 upvote
  flag
Really no benefit to this, IMOHO, except possibly stomping on someone else's implementation .. – user2864740
2 upvote
  flag
If used in the Array prototype, it should be named other than just shuffle. – Wolf
26 upvote
  flag
One could (or should) avoid extending Native Prototypes: javascriptweblog.wordpress.com/2011/12/05/… – Wédney Yuri
6 upvote
  flag
You shouldn't do this; every single array affected by this can no longer be iterated safely using for...in. Don't extend native prototypes. – Tiny Giant
7 upvote
  flag
@TinyGiant Actually: don't use for...in loops to iterate over arrays. – Conor O'Brien
1 upvote
  flag
@CᴏɴᴏʀO'Bʀɪᴇɴ for...in loops are perfectly fine for arrays, unless of course you're using some horrible code that extends the native array prototype. As long as you know that it iterates over all enumerable properties, and that it doesn't iterate properties whose values are undefined then there is no problem. – Tiny Giant

Here is a JavaScript implementation of the Durstenfeld shuffle, a computer-optimized version of Fisher-Yates:

/**
 * Randomize array element order in-place.
 * Using Durstenfeld shuffle algorithm.
 */
function shuffleArray(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;
    }
}

The Fisher-Yates algorithm works by picking one random element for each original array element, and then excluding it from the next draw. Just like randomly picking from a deck of cards.

This exclusion is done in a clever way (invented by Durstenfeld for use by computers) by swapping the picked element with the current element, and then picking the next random element from the remainder. For optimal efficiency, the loop runs backwards so that the random pick is simplified (it can always start at 0), and it skips the last element because there are no other choices anymore.

The running time of this algorithm is O(n). Note that the shuffle is done in-place. So if you do not want to modify the original array, make a copy of it first with .slice(0).

Updating to ES6 / ECMAScript 2015

The new ES6 allows us to assign two variables at once. This is especially handy when we want to swap the values of two variables, as we can do it in one line of code. Here is a shorter form of the same function, using this feature.

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}
11 upvote
  flag
p.s. The same algorithm as ChristopheD’s answer, but with explanation and cleaner implementation. – Laurens Holst
7 upvote
  flag
People are attributing the wrong person for the algorithm. It's not Fisher-Yates shuffle but Durstenfeld shuffle. The true original Fisher-Yates algorithm is runs in n^2 time, not n time – Pacerier
upvote
  flag
Could you please tell me which one you think is better for shuffling? (Link: ideone.com/pfRanN). As i tested, there is no difference between them. – Hengameh
3 upvote
  flag
It is not required to return array since JavaScript passes arrays by reference when used as function arguments. I assume this is to save on stack space, but it's an interesting little feature. Performing the shuffle on the array will shuffle the original array. – Joel Trauger
3 upvote
  flag
The implementation in this answer favors the lower end of the array. Found out the hard way. Math.random() should not be multiplied with the loop counter + 1, but with array.lengt()`. See Generating random whole numbers in JavaScript in a specific range? for a very comprehensive explanation. – Marjan Venema
3 upvote
  flag
@MarjanVenema Not sure if you're still watching this space, but this answer is correct, and the change you're suggesting actually introduces bias. See blog.codinghorror.com/the-danger-of-naivete for a nice writeup of this mistake. – smarx
upvote
  flag
Not very active anymore but I do keep track of notifications, @smarx. Thanks for that. Interesting read. What I don't understand is why I saw a definite bias towards the lower end using the code above? See softwareonastring.com/1135/perils-of-copy-paste-programming After using the solution from the answer I linked in my comment, distribution seemed much more even. – Marjan Venema
upvote
  flag
@MarjanVenema I have no explanation for that. Perhaps there was some other bug in your code. What was your sample size when you looked at the results? Perhaps the pattern you noticed at first was just dumb luck. – smarx
upvote
  flag
Code was a straight copy of this post ;) I guess it was indeed just dumb luck, but as the task attached to the outcome was considered a "chore" rather than something nice, complaints ran rampant... You know developers: there must be something wrong with your code. – Marjan Venema
upvote
  flag
@LaurensHolst why we are running from last index to first index i.e n-1 to 0? Is there any particular advantage that I'm unable to see here ?? – roottraveller
upvote
  flag
@roottraveller It simplifies the code. If it ran forwards the random range would need to be calculated (len - i), and the resulting random index would need to be offset by the current position (+ i). I allude to this in the description, but maybe this makes it more clear. Try to rewrite it yourself, and see! – Laurens Holst
upvote
  flag
for (let i = array.length - 1; i > 0; i--) should be for (let i = array.length - 1; i >= 0; i--). It appears to be missing the first array index. – bryc
upvote
  flag
@bryc As mentioned in the description, “it skips the last element because there are no other choices anymore.” Math.floor(Math.random() * (0 + 1)) will always return 0, and would thus only swap with itself, so there’s no point in doing the last swap. – Laurens Holst

Use the underscore.js library. The method _.shuffle() is nice for this case. Here is an example with the method:

var _ = require("underscore");

var arr = [1,2,3,4,5,6];
// Testing _.shuffle
var testShuffle = function () {
  var indexOne = 0;
    var stObj = {
      '0': 0,
      '1': 1,
      '2': 2,
      '3': 3,
      '4': 4,
      '5': 5
    };
    for (var i = 0; i < 1000; i++) {
      arr = _.shuffle(arr);
      indexOne = _.indexOf(arr, 1);
      stObj[indexOne] ++;
    }
    console.log(stObj);
};
testShuffle();
7 upvote
  flag
Great answer! Thanks. I prefer it to the other answers, as it encourages people to use libraries rather than copy and paste potentially buggy functions everywhere. – frabcus
33 upvote
  flag
@frabcus: There's no point in including an entire library just to get a shuffle function. – Blender
6 upvote
  flag
I disagree with @Blender. There are many reasons to include an entire library just to get a function you need. One of them is there is less risk of a bug when you write it yourself. If it's a performance problem, then you shouldn't use it. But just because it could be a performance problem doesn't mean it will be. – Daniel Kaplan
2 upvote
  flag
@tieTYT: So why do you need the rest of the library? The Fisher-Yates shuffle is trivial to implement. You don't need a library to pick a random element out of an array (I hope), so there's no reason to use a library unless you're actually going to use more than one function from it. – Blender
13 upvote
  flag
@Blender: I gave a reason why. 1) I assure you, you can introduce a bug into any code you write, no matter how trivial it is. Why risk it? 2) Don't pre-optimize. 3) 99% of the time when you need a shuffle algo, your app isn't about writing a shuffle algo. It's about something that needs a shuffle algo. Leverage others' work. Don't think about implementation details unless you have to. – Daniel Kaplan
upvote
  flag
Other good reason - once we started to use underscore, we were using it for a lot of things. We are in node, so may be different than the browser, as we don't have to load it over the network. But it's a very handy library indeed. – CargoMeister
1 upvote
  flag
Thanks for mentioning underscore.js. My question was WordPress-specific, but as of WordPress 3.4.1 underscore.js is included and loaded. core.trac.wordpress.org/ticket/21664. Just be sure to include "underscore" as a dependency when enqueueing your own .js file eg: wp_enqueue_script( 'my-script', 'path/to/my-script.js', array( 'jquery', 'underscore' ) ) and you can fully use _.shuffle() and everything else. – Tom Auger
1 upvote
  flag
There are a lot of other goodies in the underscore library, and maybe once the code is there, you might find good use for other parts of it. As a Python dev, my first thoughts were why isn't there a shuffle function in javascript, and, lo and behold, there is. – John Powell aka Barça
upvote
  flag
Great recommendation for _.js, it's pretty useful. Don't duplicate what you don't have to. – Puppy
1 upvote
  flag
seems to me odds are pretty good if you're doing anything requiring convenient, tested, prebuilt functions, you're either using underscore already anyway or you've rebuilt the wheel several times by now. (sorry no metrics available for this comment). – jsh
upvote
  flag
Since I'm already using underscore.js a lot, I don't know how I missed this feature. The more you know! – mix3d

Adding to @Laurens Holsts answer. This is 50% compressed.

function shuffleArray(d) {
  for (var c = d.length - 1; c > 0; c--) {
    var b = Math.floor(Math.random() * (c + 1));
    var a = d[c];
    d[c] = d[b];
    d[b] = a;
  }
  return d
};
2 upvote
  flag
We should be encouraging people to use _.shuffle rather than pasting code from stack overflow; and, we should be discouraging people from compressing their stack overflow answers. That's what jsmin is for. – David Jones
31 upvote
  flag
@DavidJones: Why would I include an entire 4kb library just to shuffle an array? – Blender
1 upvote
  flag
@KingKongFrog name calling is also not conductive to a assemblage of a reasonable community. – wheaties
2 upvote
  flag
is it efficient to do var b = in a loop instead of declaring b outside loop and assigning it with b = in a loop? – Alex K
1 upvote
  flag
@Alex: Javascript doesn't actually support block-scope variables (see Why does JavaScript not have block scope?). So, declaring b outside the loop probably won't make a difference. – Brian
2 upvote
  flag
@Brian Won't make a difference; the hoisting happens when the source code is parsed. No probably involved. – user2864740
upvote
  flag
Could you please tell me which one you think is better for shuffling? (Link: ideone.com/pfRanN). As i tested, there is no difference between them. – Hengameh
var shuffle = function(array) {
   temp = [];
   for (var i = 0; i < array.length ; i++) {
     temp.push(array.splice(Math.floor(Math.random()*array.length),1));
   }
   return temp;
};
upvote
  flag
This is obviously not as optimal as the Fisher-Yates algorithm, but would it work for technical interviews? – davidatthepark

[community edit: This answer is incorrect; see comments. It is being left here for future reference because the idea is not that rare.]

[1,2,3,4,5,6].sort(function() {
  return .5 - Math.random();
});
12 upvote
  flag
i like this solution, enough to give a basic random – Alex K
97 upvote
  flag
Downvoting as this isn't really that random. I don't know why it has so many upvotes. Do not use this method. It looks pretty, but isn't completely correct. Here are results after 10,000 iterations on how many times each number in your array hits index [0] (I can give the other results too): 1 = 29.19%, 2 = 29.53%, 3 = 20.06%, 4 = 11.91%, 5 = 5.99%, 6 = 3.32% – radtad
4 upvote
  flag
It's fine if you need to randomize relatively small array and not dealing with cryptographic things. I totally agree that if you need more randomness you need to use more complex solution. – deadrunk
14 upvote
  flag
150 upvote
  flag
but it's very cute – spencercooly
upvote
  flag
@radtad I did a test, the result is 16%~17% – Ivan Yan
7 upvote
  flag
The problem is that it's not deterministic, which will give wrong results (if 1 > 2 and 2 > 3, it should be given that 1 > 3, but this will not guarantee that. This will confuse the sort, and give the result commented by @radtad). – MatsLindh
2 upvote
  flag
sort() for randomizing an array has a strong bias toward keeping each element in its initial starting position in addition to the edges of the array having slightly more bias than the middle: jsfiddle.net/rcmp0aLL – Ultimater
1 upvote
  flag
Would it be random enough if I put it in a loop to run x times? When x is the size of array? – Andre Figueiredo
5 upvote
  flag
4 upvote
  flag
2 upvote
  flag
upvote
  flag
best answer if you have jquery loaded already – moeiscool
upvote
  flag
ok, any efficent and correct method that is writable in 1/3 lines? – Luca C.
4 upvote
  flag
@moeiscool How exactly is jQuery related to this answer? – Oriol
upvote
  flag
It's pretty good. [1,2,3,4,5,6].sort(function() { return (.5 - Math.random() > .5 - Math.random()); }); If you also randomly reverse it. – Master James
upvote
  flag
var ans = [1,2,3,4,5,6,8,9,10,11,12,13,14,15,16].sort(function() { return (.5 - Math.random() > 0); }); if(.5 - Math.random() > 0) ans.reverse(); else ans; – Master James
upvote
  flag
No it doesn't really work with more then a handful, depends on randomizer partly too. – Master James
upvote
  flag
why did you do (0.5 - random) ? it the same order and not doing any meaningful action. just want to understand that. – Nisim Joseph

yet another implementation of Fisher-Yates, using strict mode:

function shuffleArray(a) {
    "use strict";
    var i, t, j;
    for (i = a.length - 1; i > 0; i -= 1) {
        t = a[i];
        j = Math.floor(Math.random() * (i + 1));
        a[i] = a[j];
        a[j] = t;
    }
    return a;
}
upvote
  flag
What value does the addition of use strict provide over the accepted answer? – shortstuffsushi
upvote
  flag
To learn more about strict mode and how it influences performance you can read about it here: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – Raphael C
upvote
  flag
Hmm, could you point to something specific from the referenced document? Nothing in there seems to reference "improving performance," aside from a vague comment at the top about potentially making it difficult for the js engine to optimize. In this case, it's unclear to me what use strict would improve. – shortstuffsushi
upvote
  flag
Strict mode has been around for quite some time, and there are sufficient reads out there for anyone to make their own opinion if they should always use it or not and why. Jslint for instance makes it clear enough that you should always use strict mode. Douglas Crockford has written quite an amount of articles and some great videos on why it is important to always use strict mode not only as a good practice but also how it is interpreted differently by browser js engines such as V8. I strongly advise you to Google it and make your own opinion about it. – Raphael C
upvote
  flag
Here is an old thread about perfs in strict mode, a bit old but still relevant: //allinonescript.com/questions/3145966/… – Raphael C

A recursive solution:

function shuffle(a,b){
    return a.length==0?b:function(c){
        return shuffle(a,(b||[]).concat(c));
    }(a.splice(Math.floor(Math.random()*a.length),1));
};

This variation of Fisher-Yates is slightly more efficient because it avoids swapping an element with itself:

function shuffle(array) {
  var elementsRemaining = array.length, temp, randomIndex;
  while (elementsRemaining > 1) {
    randomIndex = Math.floor(Math.random() * elementsRemaining--);
    if (randomIndex != elementsRemaining) {
      temp = array[elementsRemaining];
      array[elementsRemaining] = array[randomIndex];
      array[randomIndex] = temp;
    }
  }
  return array;
}
Array.prototype.shuffle=function(){
   var len = this.length,temp,i
   while(len){
    i=Math.random()*len-- |0;
    temp=this[len],this[len]=this[i],this[i]=temp;
   }
   return this;
}
upvote
  flag
To truncate, you should use n >>> 0 instead of n | 0. Array indices can be higher than 2³¹-1. – Oriol

NEW!

Shorter & probably *faster Fisher-Yates shuffle algorithm

  1. it uses while---
  2. bitwise to floor (numbers up to 10 decimal digits (32bit))
  3. removed unecessary closures & other stuff

function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
 c=a.length;while(c)b=Math.random()*(--c+1)|0,d=a[c],a[c]=a[b],a[b]=d
}

script size (with fy as function name): 90bytes

DEMO http://jsfiddle.net/vvpoma8w/

*faster probably on all browsers except chrome.

If you have any questions just ask.

EDIT

yes it is faster

PERFORMANCE: http://jsperf.com/fyshuffle

using the top voted functions.

EDIT There was a calculation in excess (don't need --c+1) and noone noticed

shorter(4bytes)&faster(test it!).

function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
 c=a.length;while(c)b=Math.random()*c--|0,d=a[c],a[c]=a[b],a[b]=d
}

Caching somewhere else var rnd=Math.random and then use rnd() would also increase slightly the performance on big arrays.

http://jsfiddle.net/vvpoma8w/2/

Readable version (use the original version. this is slower, vars are useless, like the closures & ";", the code itself is also shorter ... maybe read this How to 'minify' Javascript code , btw you are not able to compress the following code in a javascript minifiers like the above one.)

function fisherYates( array ){
 var count = array.length,
     randomnumber,
     temp;
 while( count ){
  randomnumber = Math.random() * count-- | 0;
  temp = array[count];
  array[count] = array[randomnumber];
  array[randomnumber] = temp
 }
}
5 upvote
  flag
check out the performance ... 2x faster on most browsers... but needs more jsperf testers... – cocco
8 upvote
  flag
Yes, fine, but that's not the reason to make it unreadable. – georg
8 upvote
  flag
js is a language that accepts many shortcuts and different ways to write it.. while there are many slow readable functions in here i just like to show how it could be done in a more performant way, also saving some bytes... bitwise and shorthand is really underestimated here and the web is full of buggy and slow code. – cocco
1 upvote
  flag
And minifiers don't work properly....//allinonescript.com/a/21353032/2450730 – cocco
upvote
  flag
Not a slam dunk perf increase. Swapping the fy and shuffle prototype, I get fy consistently at the bottom in Chrome 37 on OS X 10.9.5 (81% slower ~20k ops compared to ~100k) and Safari 7.1 it's up to ~8% slower. YMMV, but it's not always faster. jsperf.com/fyshuffle/3 – Spig
upvote
  flag
check stats again... i already wrote chrome is slower beacuse they optimized Math, on all other the bitwise floor and while is faster. check IE, firefox but also mobile devices.Would be also nice to see opera... – cocco
upvote
  flag
mobile safari 1409(fy) vs (shuffle)1253 ,ie 31850(fy) vs (shuffle)13405 – cocco
upvote
  flag
actually shuffle at the other side it's almost the same as my fy function except the bitwise and while. – cocco
upvote
  flag
note that also the for loop works alot better on chrome than on ANY other browser. just setup a performance.time() or how it's called and test on several different browsrers... only in chrome the for loop is faster/same speed than while – cocco
upvote
  flag
btw i also got my mac mini with better results using fy, and btw what do you mean you swapped fy&shuffle prototype? changed the execution position in jsperf?? – cocco
upvote
  flag
ohh i was testing on safari 6.1 where it's also 90% faster. looks like they changed something in the 7.1 – cocco
upvote
  flag
atm i can't test on the safari 6.1 mashine – cocco
upvote
  flag
on old ipad 5.1 it's also faster.. – cocco
upvote
  flag
i added a modification.. – cocco
upvote
  flag
ungolf it and we will give more upvotes – code_monk
upvote
  flag
if i tell you the i have seen an animal in africa which has big ears and a very long nose. you would understand that it is an elefant. but the english language, also other languages, allow you to use the word elefant. javascript is also a language that has many words that can be used in different ways. i just try to use the proper words for that language. short code and performance is always important in this language. i don't use minifiers. i reread my code and optimize it. – cocco
upvote
  flag
So should you . if you don't understand something you could ask me to explain the code. Or just grab a book and read why i don't use all those multiple var, closures and extra bytes. Another thing... downvote if you think this is not a good code. noone stops you – cocco
upvote
  flag
This is a terrible answer. SO is not an obscuration competition. – Puppy
upvote
  flag
i.stack.imgur.com/ssRUr.gif use jquery puppy ;) – cocco
upvote
  flag
@cocco Why have you called numberArray(a,b) with only single parameter numberArray(10) in your fiddle? – xameeramir
upvote
  flag
Because there is no need for the second parameter...the second parameter is only a placeholder... it's to avoid "var" inside the function. Read this //allinonescript.com/questions/1737388/… – cocco
upvote
  flag
To truncate, you should use n >>> 0 instead of n | 0. Array indices can be higher than 2³¹-1. – Oriol
upvote
  flag
yes, agree even if for most situations 2³¹-1 is enough – cocco
upvote
  flag
My browser just ran the JSPerf and this answer scored lowest of all. – Stephan Bijzitter

Randomize array using array.splice()

function shuffleArray(array) {
   var temp = [];
   var len=array.length;
   while(len){
      temp.push(array.splice(Math.floor(Math.random()*array.length),1)[0]);
      len--;
   }
   return temp;
}
//console.log("Here >>> "+shuffleArray([4,2,3,5,8,1,0]));

demo

upvote
  flag
Essentially the same as Tophe posted more than a year before. – trincot

First of all, have a look here for a great visual comparison of different sorting methods in javascript.

Secondly, if you have a quick look at the link above you'll find that the random order sort seems to perform relatively well compared to the other methods, while being extremely easy and fast to implement as shown below:

function shuffle(array) {
  var random = array.map(Math.random);
  array.sort(function(a, b) {
    return random[array.indexOf(a)] - random[array.indexOf(b)];
  });
}

Edit: as pointed out by @gregers, the compare function is called with values rather than indices, which is why you need to use indexOf. Note that this change makes the code less suitable for larger arrays as indexOf runs in O(n) time.

upvote
  flag
Array.prototype.sort passes in two values as a and b, not the index. So this code doesn't work. – gregers
upvote
  flag
@gregers you're right, I've edited the answer. Thanks. – 0sh
upvote
  flag
This is not very random. Depending on the implementation of sort, an element at the lowest array index might require more comparisons in order to get to the highest index than the element next to the highest index. This means that it is less likely for the element at the lowest index to get to the highest index. – 1' OR 1 --

Randomize array

 var arr = ['apple','cat','Adam','123','Zorro','petunia']; 
 var n = arr.length; var tempArr = [];

 for ( var i = 0; i < n-1; i++ ) {

    // The following line removes one random element from arr 
     // and pushes it onto tempArr 
     tempArr.push(arr.splice(Math.floor(Math.random()*arr.length),1)[0]);
 }

 // Push the remaining item onto tempArr 
 tempArr.push(arr[0]); 
 arr=tempArr; 
upvote
  flag
There shouldn't be a -1 for n as you used < not <= – Mohebifar

I found this variant hanging out in the "deleted by author" answers on a duplicate of this question. Unlike some of the other answers that have many upvotes already, this is:

  1. Actually random
  2. Not in-place (hence the shuffled name rather than shuffle)
  3. Not already present here with multiple variants

Here's a jsfiddle showing it in use.

Array.prototype.shuffled = function() {
  return this.map(function(n){ return [Math.random(), n] })
             .sort().map(function(n){ return n[1] });
}
upvote
  flag
(I suspect it was deleted as it is a very inefficient way to randomize the array, especially for larger arrays... whereas the accepted answer, and a number of other clones of that answer randomize in-place). – WiredPrairie
1 upvote
  flag
Yeah, but given that the well-known wrong answer is still up with a bunch of votes, an inefficient but correct solution should at least be mentioned. – Daniel Martin
upvote
  flag
Which one is the "well-known wrong answer"? – WiredPrairie
upvote
  flag
[1,2,3,4,5,6].sort(function() { return .5 - Math.random(); }); - it doesn't give a random sort, and if you use it you can end up embarrassed: robweir.com/blog/2010/02/microsoft-random-browser-ballot.htm‌​l – Daniel Martin
1 upvote
  flag
You need to use .sort(function(a,b){ return a[0] - b[0]; }) if you want the sort to compare values numerically. The default .sort() comparator is lexicographic, meaning it will consider 10 to be less than 2 since 1 is less than 2. – 4castle
upvote
  flag
@4castle Okay, I updated the code, but am going to revert it: the distinction between lexicographic order and numerical order doesn't matter for numbers in the range that Math.random() produces. (that is, lexicographic order is the same as numeric order when dealing with numbers from 0 (inclusive) to 1 (exclusive)) – Daniel Martin

Fisher-Yates shuffle in javascript. I'm posting this here because the use of two utility functions (swap and randInt) clarifies the algorithm compared to the other answers here.

function swap(arr, i, j) { 
  // swaps two elements of an array in place
  var temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}
function randInt(max) { 
  // returns random integer between 0 and max-1 inclusive.
  return Math.floor(Math.random()*max);
}
function shuffle(arr) {
  // For each slot in the array (starting at the end), 
  // pick an element randomly from the unplaced elements and
  // place it in the slot, exchanging places with the 
  // element in the slot. 
  for(var slot = arr.length - 1; slot > 0; slot--){
    var element = randInt(slot+1);
    swap(arr, element, slot);
  }
}
var shuffledArray = function(inpArr){
    //inpArr - is input array
    var arrRand = []; //this will give shuffled array
    var arrTempInd = []; // to store shuffled indexes
    var max = inpArr.length;
    var min = 0;
    var tempInd;
    var i = 0;

    do{
        //generate random index between range
        tempInd = Math.floor(Math.random() * (max - min));
        //check if index is already available in array to avoid repetition
        if(arrTempInd.indexOf(tempInd)<0){
            //push character at random index
            arrRand[i] = inpArr[tempInd];
            //push random indexes
            arrTempInd.push(tempInd);
            i++;
        }
    }
    // check if random array length is equal to input array length
    while(arrTempInd.length < max){
        return arrRand; // this will return shuffled Array
    }
};

Just pass the array to function and in return get the shuffled array

With ES2015 you can use this one:

Array.prototype.shuffle = function() {
  let m = this.length, i;
  while (m) {
    i = (Math.random() * m--) >>> 0;
    [this[m], this[i]] = [this[i], this[m]]
  }
  return this;
}

Usage:

[1, 2, 3, 4, 5, 6, 7].shuffle();
4 upvote
  flag
To truncate, you should use n >>> 0 instead of ~~n. Array indices can be higher than 2³¹-1. – Oriol
1 upvote
  flag
Destructuring like this makes for such a clean implementation +1 – lukejacksonn

based on the Fisher-Yates Shuffle, you can try this reusable array-shuffle component. Example:

shuffle([1, 2, 3, 4, 5]) // => [2, 4, 1, 5, 3]

I also like this Lodash function which returns a new array and leaves the original array unchanged:

function shuffle(array) {
    var rand, index = -1,
        length = array.length,
        result = Array(length);
    while (++index < length) {
        rand = Math.floor(Math.random() * (index + 1));
        result[index] = result[rand];
        result[rand] = array[index];
    }
    return result;
}

(Proper disclosure: I'm on the CoCycles team.)

1 upvote
  flag
You might want to add: Note this returns a new array and leaves the original array unchanged. – GitaarLAB
upvote
  flag
Is this disclosure relevant to the question? Is CoCycles an array sorting algorithm company? – shortstuffsushi

Considering apply it to in loco or to a new immutable array, following other solutions, here is a suggested implementation:

Array.prototype.shuffle = function(local){
  var a = this;
  var newArray = typeof local === "boolean" && local ? this : [];
  for (var i = 0, newIdx, curr, next; i < a.length; i++){
    newIdx = Math.floor(Math.random()*i);
    curr = a[i];
    next = a[newIdx];
    newArray[i] = next;
    newArray[newIdx] = curr;
  }
  return newArray;
};

Ronald Fisher and Frank Yates shuffle

ES2015 (ES6) release

Array.prototype.shuffle2 = function () {
    this.forEach(
        function (v, i, a) {
            let j = Math.floor(Math.random() * (i + 1));
            [a[i], a[j]] = [a[j], a[i]];
        }
    );
    return this;
}

Jet optimized ES2015 (ES6) release

Array.prototype.shuffle3 = function () {
    var m = this.length;
    while (m) {
        let i = Math.floor(Math.random() * m--);
        [this[m], this[i]] = [this[i], this[m]];
    }
    return this;
}
2 upvote
  flag
This is the same as BrunoLM's answer – Oriol
upvote
  flag
May be, but I don't thik so: 1) in my examples there are 2 - releases, one - for full understending, second - ready to use optimized version wich 2) not use low level ninja's tricks, 3) works in ANY environment with ES6. Please, don't mess the novices And, hmmm.. BrunoLM updated the answer, and now his anser is more powerful: in BrunoLM's code is not used Math but direct low level digital operations, so it's MUCH-MUCH faster. Now (after update) it's works correctly in ANY ES6 envs and strongly recomended, especially for big arrays. Thank u, Oriol. – SynCap

$=(m)=>console.log(m);

//----add this method to Array class 
Array.prototype.shuffle=function(){
  return this.sort(()=>.5 - Math.random());
};

$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());

2 upvote
  flag
This is very bad as the elements have a high probability of staying near their original position or barely moving from there. – Jacque Goupil
1 upvote
  flag
If it bad , chain it twice or more : array.shuffle().shuffle().shuffle() – Abdennour TOUMI
4 upvote
  flag
Repeating the call slightly reduces the probabilities of getting very similar results, but it doesn't make it a true random shuffle. In the worst case scenario, even an infinite number of calls to shuffle could still give the exact same array we started with. The Fisher-Yates algorithm is a much better and still efficient choice. – Jacque Goupil
3 upvote
  flag
Not the same awful answer again, please. – Oriol

the shortest arrayShuffle function

function arrayShuffle(o) {
    for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
}
upvote
  flag
Apparently you are doing Sattolo's instead of Fisher-Yates (Knuth, unbiased). – Arthur2e5

I see no one has yet given a solution that can be concatenated while not extending the Array prototype (which is a bad practice). Using the slightly lesser known reduce() we can easily do shuffling in a way that allows for concatenation:

var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle).map(n => n*n);

You'd probably want to pass the second parameter [], as otherwise if you try to do this on an empty array it'd fail:

// Both work. The second one wouldn't have worked as the one above
var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle, []).map(n => n*n);
var randomsquares = [].reduce(shuffle, []).map(n => n*n);

Let's define shuffle as:

var shuffle = (rand, one, i, orig) => {
  if (i !== 1) return rand;  // Randomize it only once (arr.length > 1)

  // You could use here other random algorithm if you wanted
  for (let i = orig.length; i; i--) {
    let j = Math.floor(Math.random() * i);
    [orig[i - 1], orig[j]] = [orig[j], orig[i - 1]];
  }

  return orig;
}

You can see it in action in JSFiddle or here:

var shuffle = (all, one, i, orig) => {
    if (i !== 1) return all;

    // You could use here other random algorithm here
    for (let i = orig.length; i; i--) {
        let j = Math.floor(Math.random() * i);
        [orig[i - 1], orig[j]] = [orig[j], orig[i - 1]];
    }

    return orig;
}

for (var i = 0; i < 5; i++) {
  var randomarray = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle, []);
  console.log(JSON.stringify(randomarray));
}

upvote
  flag
It seems that you're exchanging for too much times. With reduce you can totally perform a streaming "inside-out" Fisher-Yates that uses (acc, el) => { acc.push(el); let i = Math.floor(Math.random() * (acc.length)); [acc[i], acc[acc.length - 1]] = [acc[acc.length - 1], acc[i]]; return acc; } as the callback. (Adapted from public domain code on zhihu.) – Arthur2e5

From a theoretical point of view, the most elegant way of doing it, in my humble opinion, is to get a single random number between 0 and n!-1 and to compute a one to one mapping from {0, 1, …, n!-1} to all permutations of (0, 1, 2, …, n-1). As long as you can use a (pseudo-)random generator reliable enough for getting such a number without any significant bias, you have enough information in it for achieving what you want without needing several other random numbers.

When computing with IEEE754 double precision floating numbers, you can expect your random generator to provide about 15 decimals. Since you have 15!=1,307,674,368,000 (with 13 digits), you can use the following functions with arrays containing up to 15 elements and assume there will be no significant bias with arrays containing up to 14 elements. If you work on a fixed-size problem requiring to compute many times this shuffle operation, you may want to try the following code which may be faster than other codes since it uses Math.random only once (it involved several copy operations however).

The following function will not be used, but I give it anyway; it returns the index of a given permutation of (0, 1, 2, …, n-1) according to the one to one mapping used in this message (the most natural one when enumerating permuations); it is intended to work with up to 16 elements:

function permIndex(p) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000];
    var tail = [];
    var i;
    if (p.length == 0) return 0;
    for(i=1;i<(p.length);i++) {
        if (p[i] > p[0]) tail.push(p[i]-1);
        else tail.push(p[i]);
    }
    return p[0] * fact[p.length-1] + permIndex(tail);
}

The reciprocal of the previous function (required for your own question) is below; it is intended to work with up to 16 elements; it returns the permutation of order n of (0, 1, 2, …, s-1):

function permNth(n, s) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000];
    var i, j;
    var p = [];
    var q = [];
    for(i=0;i<s;i++) p.push(i);
    for(i=s-1; i>=0; i--) {
        j = Math.floor(n / fact[i]);
        n -= j*fact[i];
        q.push(p[j]);
        for(;j<i;j++) p[j]=p[j+1];
    }
    return q;
}

Now, what you want merely is:

function shuffle(p) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000];
    return permNth(Math.floor(Math.random()*fact[p.length]), p.length).map(
            function(i) { return p[i]; });
}

It should work for up to 16 elements with a little theoretical bias (though unnoticeable from a practical point of view); it can be seen as fully usable for 15 elements; with arrays containing less than 14 elements, you can safely consider there will be absolutely no bias.

I was thinking about oneliner to paste in console. All tricks with .sort was giving wrong results, here is my implementation:

 ['Bob', 'Amy', 'Joy'].map((person) => `${Math.random().toFixed(10)}${person}`).sort().map((person) => person.substr(12));

But don't use it in production code, it's not optimal and works with strings only.

upvote
  flag
It works with any kind of variable: array.map(e => [Math.random(), e]).sort((a, b) => a[0] - b[0]).map(e => e[1]) (but is not optimal). – Gustavo Rodrigues
upvote
  flag
That is a very cute solution. – superluminary

A very simple way for small arrays is simply this:

const someArray = [1, 2, 3, 4, 5];

someArray.sort(() => Math.random() * 2 - 1);

It's probably not very efficient, but for small arrays this works just fine :)

upvote
  flag
Nice one, but does generate a complete random elements every time? – Azarus
upvote
  flag
Not quite sure if I understood you correctly. This approach will indeed shuffle the array in a random way (albeit pseudo-random) every time you call the sort array - it's not a stable sort, for obvious reasons. – Kris Selbekk
upvote
  flag
I didn't quite understand the down-vote here - care to comment? =) – Kris Selbekk
upvote
  flag
Wasn't me, but however i dont understand why its downvoted either. – Azarus
1 upvote
  flag
For the same reasons as explained at //allinonescript.com/a/18650169/28234 . This is much more likely to leave early elements near the start of the array. – AlexC
1 upvote
  flag
This is a great, easy one-liner for when you need to scramble an array, but don't care too much about having the results be academically provably random. Sometimes, that last few inches to perfection take more time than it's worth. – Daniel Griscom

function shuffleArray(array) {
        // Create a new array with the length of the given array in the parameters
        const newArray = array.map(() => null);

        // Create a new array where each index contain the index value
        const arrayReference = array.map((item, index) => index);

        // Iterate on the array given in the parameters
        array.forEach(randomize);
        
        return newArray;

        function randomize(item) {
            const randomIndex = getRandomIndex();

            // Replace the value in the new array
            newArray[arrayReference[randomIndex]] = item;
            
            // Remove in the array reference the index used
            arrayReference.splice(randomIndex,1);
        }

        // Return a number between 0 and current array reference length
        function getRandomIndex() {
            const min = 0;
            const max = arrayReference.length;
            return Math.floor(Math.random() * (max - min)) + min;
        }
    }
    
console.log(shuffleArray([10,20,30,40,50,60,70,80,90,100]));

A simple modification of CoolAJ86's answer that don't modify original array

 /**
 * Returns a new array whose contents are a copy shuffled of the array.
 * @param {Array} a items to shuffle.
 * //allinonescript.com/a/2450976/1673761
 */
const shuffle = (array) => {
  let currentIndex = array.length;
  let temporaryValue;
  let randomIndex;
  const newArray = array.slice();
  // While there remain elements to shuffle...
  while (currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    // And swap it with the current element.
    temporaryValue = newArray[currentIndex];
    newArray[currentIndex] = newArray[randomIndex];
    newArray[randomIndex] = temporaryValue;
  }
  return newArray;
};

Just to have a finger in the pie. Here i present a recursive implementation of Fisher Yates shuffle (i think). It gives uniform randomness.

function shuffle(a){
  return a.length ? a.splice(~(Math.random()*a.length),1).concat(shuffle(a))
                  : a;
}

console.log(JSON.stringify(shuffle([0,1,2,3,4,5,6,7,8,9])));

Some of the answers could be shortened with the latest ES6.

Shuffle Array In place

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

ES6 allows us to assign two values at once. This is especially handy in line 4 above, where two variables are swapped in one line of code.

Leave original Array intact and return a shuffled array

If you want to make a more pure function, and leave the original array intact, you can simply duplicate the array and then run the same algorithm.

function getShuffledArray (arr){
    let newArr = arr.slice();
    for (var i = newArr.length - 1; i > 0; i--) {
        var rand = Math.floor(Math.random() * (i + 1));
        [newArr[i], newArr[rand]]=[newArr[rand], newArr[i]];
    }
    return newArr;
}

An ascending Algorithm

The algorithm below uses an ascending loop. It is less intuitive, yet short and valid.

function getShuffledArray (arr){
    let newArr = arr.slice();
    for (let i = 1; i < newArr.length ; i++) {
        const rand = Math.floor( Math.random() * (i + 1) ); 
        [newArr[i], newArr[rand]] = [newArr[rand], newArr[i]];
    }
    return newArr;
}

Testing Reliability of the Randomising function

I used the function bellow to test the reliability of the randomising function. This function prints out the distribution of values in each position.

function testShuffledArrayFun(getShuffledArrayFun){
    let arr = [0,1,2,3,4];
    var length = arr.length;

    var countArr = [] // for for each possible position in the shuffledArr, for each possible value, we'll create a counter. the counter of element 0 in position 0 will be countArr[0][0]
    for (var i=0 ; i<length ; i++){
        let positionArr= [];
        for (var j=0 ; j<length ; j++){
            positionArr.push(0); // Set Counter To 0
        }
        countArr.push(positionArr);
    }

    const n = 10000;
    for (var i=0 ; i<n ; i++){
        // We'll call getShuffledArrayFun for n times. And for each time we'll increment the counter.  At the end we'll print the results so we can verify that the function actually randomises the array.
        var shuffledArr = getShuffledArrayFun(arr);
        shuffledArr.forEach(
            (value, key) => {countArr[key][value]++}
        );
    }

    countArr.forEach(
        (positionArr,key) => {
            console.log(`Position ${key}:`);
            positionArr.forEach(
                (count,originalValue) => {
                    console.log(`The Value ${originalValue} appeared ${count*100/n}% `);
                }
            );
        }
    );
}

running the test on both getShuffledArray functions, both in chrome and in node, displayed in the console an even distribution. This is in accordance with what we would expect from a randomizing function.

upvote
  flag
So, where is the ES6(ES2015) ? [array[i], array[rand]]=[array[rand], array[i]] ? Maybe you can outline how that works. Why do you choose to iterate downwards? – sheriffderek
upvote
  flag
@sheriffderek Yes, the ES6 feature I'm using is the assignment of two vars at once, which allows us to swap two vars in one line of code. – Ben
upvote
  flag
Credit to @sheriffderek who suggested the ascending Algorithm. The ascending algorithm could be proved in induction. – Ben

All the other answers are based on Math.random() which is fast but not suitable for cryptgraphic level randomization.

The below code is using the well known Fisher-Yates algorithm while utilizing Web Cryptography API for cryptographic level of randomization.

var d = [1,2,3,4,5,6,7,8,9,10];

function shuffle(a) {
	var x, t, r = new Uint32Array(1);
	for (var i = 0, c = a.length - 1, m = a.length; i < c; i++, m--) {
		crypto.getRandomValues(r);
		x = Math.floor(r / 65536 / 65536 * m) + i;
		t = a [i], a [i] = a [x], a [x] = t;
	}

	return a;
}

console.log(shuffle(d));

You can do it easily with map and sort:

let unshuffled = ['hello', 'a', 't', 'q', 1, 2, 3, {cats: true}]

let shuffled = unshuffled
  .map((a) => ({sort: Math.random(), value: a}))
  .sort((a, b) => a.sort - b.sort)
  .map((a) => a.value)
  1. We put each element in the array in an object, and give it a random sort key
  2. We sort using the random key
  3. We unmap to get the original objects

You can shuffle polymorphic arrays, and the sort is as random as Math.random, which is good enough for most purposes.

1 upvote
  flag
This is short and sweet. – Rexford
1 upvote
  flag
@superluminary Oops, you're right. Notice that this answer already used the same approach. – Bergi
upvote
  flag
@Bergi - Ah yes, you are right, although I think my implementation is slightly prettier. – superluminary

a shuffle function that doesn't change the source array

Here are my 5 cents. If you don't wish your shuffle function to mutate the source array, you can copy it to a local variable, then do the rest with a simple shuffling logic.

function shuffle(array) {
  var result = [], source = array.concat([]);

  while (source.length) {
    let index = Math.floor(Math.random() * source.length);
    result.push(source[index]);
    source.splice(index, 1);
  }

  return result;
}

Shuffling logic: pick up a random index, then add the corresponding element to the result array and delete it from the source array copy. Repeat this action until the source array gets empty.

And if you really want it short, here's how far I could get:

function shuffle(array) {
  var result = [], source = array.concat([]);

  while (source.length) {
    let index = Math.floor(Math.random() * source.length);
    result.push(source.splice(index, 1)[0]);
  }

  return result;
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.