One useful thing that Actionscript doesn’t offers is the ability to shuffle an array, however this can be accomplished in a blink of an eye and with very few lines of code. Before to implement my own solution, I looked on the web, but solutions provided by others developers looks too complex and too long to type. What I found was based on a for loop and several line of codes to fill a secondary array with the elements in a new random order. My solution instead is based on a while loop (3 lines of code only):
1 2 3 4 | var arr2:Array = []; while (arr.length > 0) { arr2.push(arr.splice(Math.round(Math.random() * (arr.length - 1)), 1)[0]); } |
How it works?
First we have to create a new array (arr2) which will contains the elements from the base ordered array (arr), then we use a while loop, which can be translated into english as: “do this until base array is not empty”. Inside the loop, we push into the second array a random element from the first array and, at the same time, we remove that element from its array. Array’s method splice() in fact, removes one or more elements from an array and returns an array containing the deleted elements, that in our case is only one (as specified in the second argument). The first argument of the method represent the starting index from which to start to delete, this is dynamically calculated by using the Math.random() method (which returns a number between 0 and 1), then multiplied by the length of the base array minus 1, because array length is always 1 greater than elements array contains (cause array indexing starts from zero), finally this number is rounded to the nearest integer by Math.round(), in order to access an exact index.
I think this is the best and shorter way to implement a shuffle functionality :)


March 24th, 2009 2:23 am
Thanks David, it’s simple, it’s short, it’s elegant and it works; as opposed to many other ‘sollutions’ I found on the webs.
March 24th, 2009 3:33 am
You are welcome Marc ;)
April 19th, 2009 1:02 pm
I actually arrived at this exact same solution through trial and error, and just wanted to see if anyone had arrived at anything better. IMO this is all you need. Cheers…
May 19th, 2009 5:47 am
Acctually your solution, although short code-wise, is approximately twice as slow as e.g. this:
function doRandArray7(a:Array):Array {
var nLen:Number = a.length;
var aRand:Array = a.slice();
var nRand:Number;
var oTemp:Object;
for (var i:Number = 0; i < nLen; i++) {
oTemp = aRand[i];
nRand = i + (random(nLen – i));
aRand[i] = aRand[nRand];
aRand[nRand] = oTemp;
}
return aRand;
}
May 19th, 2009 5:58 am
I haven’t tried your code, but I’m sure you are right. Anyway I’m not saying my solution is the fastest but sure the shorter, each developer is free to choose the approach he prefers.
My only goal was to show an alternative and really simplified technique to implement a shuffle() method ;)
June 19th, 2009 7:38 am
Thanks this worked very well. Just what I was looking for, something simple.
June 23rd, 2009 11:19 am
Thanks Dave :)
August 10th, 2009 8:13 am
Hi!
I don’t understand where that arr thing is coming from.
“which will contains the elements from the base ordered array” – Could you explain what you mean? Please help me! The code looks so easy :D
August 10th, 2009 9:20 am
Hi Mark, that “arr” is an argument (the original array to shuffle), imagine a function like this:
public function shuffle(arr:Array):Array {
var arr2:Array = [];
while (arr.length > 0) {
arr2.push(arr.splice(Math.round(Math.random() * (arr.length – 1)), 1)[0]);
}
return arr2;
}
Is it clear now?
September 17th, 2009 6:53 am
Yes, thank you very much!
September 18th, 2009 4:16 am
Hey Dave,
Thanks for the AS3 post & comments on how to implement the shuffle code,
nice work!
btw, I enjoy using Arduino Board (from Italy) to create projects that cross code, design & art – might be something you’re interested in? – check my site if you are curious.
Cheers mate,
/Rich
October 12th, 2009 12:59 am
Hi Dave, thank you very much for this very smart code.
I had tried another solution by MRSTEEL, that required much more code, and was focusing on execution speed. But testing it on a small array (23 items), I realized the randomness seemed very poor: the first item of the original array seemed to remain in the first position half of the time, and seemed to never make it further than fourth position.
Your code doesn’t seem to suffer from the same defect.
So as far as I’m concerned, your code is very satisfying in terms of lines spared, and quality of randomness.
October 12th, 2009 1:23 am
@deesnay: Thank you so much ;-)
November 24th, 2009 4:46 pm
hey Dave thanks alot. I appreciate your code and explanation. Im new to action script and i wasnt looking forward to spending a few hours trying to figure this out. All the other examples i read were too complex. 3 lines of code…you can beat that really. Thanks Alot!
December 14th, 2009 7:23 am
Thank you!
April 18th, 2010 6:14 pm
Thanks Dave – tasty.
May 27th, 2010 6:46 pm
Thanks Dave.
I finished home-work.
You had help me.
August 12th, 2010 6:04 am
I used your code, and tweaked it a bit, heres my variation…I get to use the same script for shuffling several arrays…Cheers
function _getRandom(e:Array) {
var arr2:Array = new Array();
while (e.length != 0) {
arr2.push(e.splice(Math.floor(Math.random() * e.length)));
}
e = arr2;
}
_getRandom(firsthalf);
_getRandom(secondhalf);
August 12th, 2010 6:14 am
I think I made a little mistake, I think I have corrected it….
function _getRandom(e:Array) {
var arr2:Array = new Array();
while (e.length != 0) {
arr2.push(e.splice(Math.floor(Math.random() * e.length)));
}
while (arr2.length!=0) {
e.push(arr2.shift());
}
}
_getRandom(firsthalf);
_getRandom(secondhalf);
September 23rd, 2010 4:24 pm
Great blog post, I’ve been looking for that…
Kind Regards,
Jeanette
December 3rd, 2010 9:43 am
Thank you, I am working on something small and not so worried about memory usage, and this solution fit perfectly in my code. Cheers!
Tabby
December 28th, 2010 6:27 am
Nice work ! Thank you for sharing
February 20th, 2011 5:16 am
I have tested Marten’ solution and to me it seems the best because :
- it produces a true randomization (even chances for every items to occupy any place in the final array), unlike methods based on the sort function I have seen,
- it’s faster than the methods based on the splice function.
February 28th, 2011 8:58 am
Thanks Dave – this was just what I needed!
July 2nd, 2011 11:12 am
var array1:Array=new Array(“1″,”2″,”3″,”4″,”5″,”6″,”7″);
var array2:Array=new Array(“1a”,”2a”,”3a”,”4a”,”5a”,”6a”,”7a”);
var newArray1:Array=[];
var newArray2:Array=[];
//this is ok
//var newArray2:Array=new Array();
while (array1.length > 0) {
var r=Math.random();
var s=r;
newArray1.push(array1.splice(Math.round(r * (array1.length – 1)), 1)[0]);
newArray2.push(array2.splice(Math.round(s * (array2.length – 1)), 1)[0]);
}
trace(newArray1);
trace(newArray2);
July 28th, 2011 4:34 am
Beautiful! Many thanks Dave!
August 3rd, 2011 9:56 pm
Cheers! Thanks for sharing.
August 20th, 2011 6:06 pm
private function init():void
{
var nums:Vector. = new Vector.();
nums.push(10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
trace(“Ordered: ” + nums);
trace(“Shuffled: ” + shuffle(nums));
trace(“Ordered: ” + nums);
}
private function shuffle(vec:Vector.):Vector.
{
var original:Vector. = vec.slice();
var result:Vector. = new Vector.();
while (original.length > 0)
{
var randomIndex:int = Math.round((original.length – 1) * Math.random());
result.push(original[randomIndex]);
original.splice(randomIndex, 1);
}
return result;
}
August 20th, 2011 6:08 pm
posting the above removed the proper code for new Vector object instantiation.
September 22nd, 2011 10:37 am
You’re The Man!! Thanks a lot