Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Fisher–Yates shuffle
function(
a, // an array
b // placeholder
){
for(b=a.length ;b ;)
a.push(a.splice(Math.random()*b--,1)[0]) // randomly move an element to the end
}
function(a,b){for(b=a.length;b;)a.push(a.splice(Math.random()*b--,1)[0])}
function(a){with(a)for(a=length;a;)push(splice(Math.random()*a--,1)[0])} // with version and save 1 byte thanks to @subzey
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 YOUR_NAME_HERE <YOUR_URL_HERE>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "shuffle",
"description": "Shuffle an array.",
"keywords": [
"Fisher–Yates",
"shuffle",
"array"
]
}
<!DOCTYPE html>
<title>Foo</title>
<div>Expected value: <b>Random numbers</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
// write a small example that shows off the API for your example
// and tests it in one fell swoop.
var myFunction = function(a,b){for(b=a.length;b;)a.push(a.splice(Math.random()*b--,1)[0])}
var a = [1,2,3,4,5,6,7,8,9];
myFunction(a);
document.getElementById( "ret" ).innerHTML = a
</script>
@subzey

This comment has been minimized.

Copy link

commented Nov 8, 2011

Nice one!

with black magic may save 1 byte. But I don't sure it's worth.

function(a){with(a)for(a=length;a;)push(splice(0|Math.random()*a--,1)[0])}
@tsaniel

This comment has been minimized.

Copy link
Owner Author

commented Nov 8, 2011

Thanks, the with trick is awesome!
However, I think it's not worth it.
Actually, .sort(function(){return.5-Math.random()}) can be the shortest code but inefficient.

@vjeux

This comment has been minimized.

Copy link

commented Dec 12, 2011

It looks like you don't need to cast the first argument of splice into an int, the function already does it.

[1, 2, 3].splice(1, 1)
> [2]
[1, 2, 3].splice(1.2, 1)
> [2]

I tested it on ie9, chrome, firefox and opera. Not sure if it works on all versions but I suppose it would

@tsaniel

This comment has been minimized.

Copy link
Owner Author

commented Dec 12, 2011

ES3 15.4.4.12 says it would.

4. Call ToInteger(start).

@vjeux: thanks for your great work!

@williammalo

This comment has been minimized.

Copy link

commented Mar 20, 2012

you can make it shorter

function(a,b){for(b in a)a.push(a.splice(Math.random()*b,1))}

@tsaniel

This comment has been minimized.

Copy link
Owner Author

commented Mar 21, 2012

@williammalo: Thanks for you advice!
But I am afraid that there will be an error if you input a non-array object.

@williammalo

This comment has been minimized.

Copy link

commented Mar 21, 2012

@tsaniel: "for in" loops also work with objects, for example: {foo:bar,lorem:ipsum} if thats whats bothering you.
If you don't change your own function, I'll make a fork =D

@tsaniel

This comment has been minimized.

Copy link
Owner Author

commented Mar 22, 2012

I think an object does not have methods "push" and "splice"...
Anyway, feel free to fork the code :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.