How to Pick Random Unique Elements out of an Array

I have an array of sprites. I’m using the following code to apply an animation to a randomly chosen sprite in my array:


var i : int = Math.floor(Math.random() * tempTileArray.length);
var child : Tile = tempTileArray*;
child.bonusTileEffect();

My question is how do grab more than one random element from my array? I would like to apply my animation to x random sprites in my array.

Appreciate any help you can offer.

You’re gonna wann splice out the tiles that you have already applied the code to and then simply run your code x amount of times.

for(var i:int = 0; i < x; i++) {
	var child : Tile = tempTileArray.splice(Math.floor(Math.random() * tempTileArray.length), 1)[0];
	child.bonusTileEffect();
}

Thnks for the reply TheCanadian. Your method makes sense, but I need to keep the original array intact as I have other other functions that use it. Is there another way to select x number of random elements from an array?

Create a temporary array that is the same as the original and perform the manipulations on that.


var myArray:Array = ["cat", "dog", "rat"]
var tempArray:Array = myArray;

trace(tempArray) //traces "cat", "dog", "rat"

Take a look at my continuous shuffling algorithm. It’s a very elegant solution for this set of problems.
Never-ending Shuffled Sequences - When Random is too Random

If each item exists only once there can be still a repetition when it wraps around. So, that’s a special case you might want to handle. The simplest method would be to check if the currently drawn item matches the previous one and if so draw again. While that slightly skews the distribution, it’s probably good enough.

[QUOTE=Anogar;2343300]Create a temporary array that is the same as the original and perform the manipulations on that.


var myArray:Array = ["cat", "dog", "rat"]
var tempArray:Array = myArray;

trace(tempArray) //traces "cat", "dog", "rat"

[/QUOTE]
Noooooo!!! Both variables are referencing the same array.

The idea’s right though but you’ll have to make a seperate object. I use the splice method for that as well.

var a:Array = [];
var b:Array = a.splice();

trace(a == b);

Durrr, you’re right, ignore me and my brainfart. :lol:

I think you meant [FONT=Courier New]slice [/FONT]though, not [FONT=Courier New]splice[/FONT]. Obviously, they both work, but if you start trying to only return certain elements you’ll start ripping them out of the original.


var myArray:Array = ["cat", "dog", "rat"]
var tempArray = myArray.splice();

tempArray = [];

trace(tempArray); //traces nothing
trace(myArray); //traces the original array

Forgive my ignorance here, but wouldn’t using the new operator solve this without slice / splicing?

var myArray:Array = new Array('cat', 'dog','bird');
var otherArray:Array = new Array(myArray);

otherArray.push('fish');

trace (myArray == otherArray);

[QUOTE=Anogar;2343321]Durrr, you’re right, ignore me and my brainfart. :lol:

I think you meant [FONT=Courier New]slice [/FONT]though, not [FONT=Courier New]splice[/FONT]. Obviously, they both work, but if you start trying to only return certain elements you’ll start ripping them out of the original. [/QUOTE]
Ignore my brainfart :hugegrin:

[QUOTE=dthought;2343324]Forgive my ignorance here, but wouldn’t using the new operator solve this without slice / splicing?

var myArray:Array = new Array('cat', 'dog','bird');
var otherArray:Array = new Array(myArray);

otherArray.push('fish');

trace (myArray == otherArray);

[/QUOTE]

No because that pushes the entire original array as the first element of the new one:

var myArray:Array = new Array('cat', 'dog','bird');
var otherArray:Array = new Array(myArray);
trace(otherArray[0] is Array); //true

Yeah, as TheCanadian mentioned, that’ll stick it as the first element in the new array, so tempArray[0] would trace the entire original array.

The reason to use slice over splice is that slice is non-destructive.

Aha - well yes, that makes sense. I should have put a little more thought into it. One of those days, I guess :wink:

You could maybe do something like this

var indices = new Array();
var selectedSprites:Array = new Array(); // to hold the ones we pick

for(var i:int = 0; i<indices.length; i++)
{
    indices* = i;
}

for(i = 0; i < 4; i++) // say you want to pick 4 sprites
{
    // pick a random position in indices
    var r = Math.floor(Math.random()*indices.length);
    
    // get the sprite in that position
    var pickedSprite = tempTileArray[r];
    
    // add that sprite to our selection
    selectedSprites.push(pickedSprite);
    
    // remove that position from indices
    indices.splice(i,1);
    
}