Reputation: 6843
I have an array of objects. Each object has a property called name. I want to efficiently remove an object with a particular name from the array. Is this the BEST way?
private function RemoveSpoke(Name:String):void {
var Temp:Array=new Array;
for each (var S:Object in Spokes) {
if (S.Name!=Name) {
Temp.push(S);
}
}
Spokes=Temp;
}
Upvotes: 6
Views: 19363
Reputation: 181
Here's an efficient function in terms of reusability, allowing you to do more than remove the element. It returns the index, or -1 if not found.
function searchByProp(arr:Array, prop:String, value:Object): int { var item:Object; var n: int = arr.length; for(var i:int=n;i>0;i--) { item = arr[i-1]; if(item.hasOwnProperty(prop)) if( value == item[prop] ) return i-1; } return -1; }
Upvotes: 0
Reputation: 11
In general you should prefer the old for-loop over "for each" and "for each in" and use Vector if your elements are of the same type. If performance is really important you should consider using a linked list.
Check out Grant Skinners slides http://gskinner.com/talks/quick/ and Jackson Dunstan's Blog for more infos about optimization.
Upvotes: 1
Reputation:
Perhaps this technique (optimized splice method by CJ's) will further improve the one proposed by Quasimondo:
http://cjcat.blogspot.com/2010/05/stardust-v11-with-fast-array-splicing_21.html
Upvotes: 0
Reputation: 6715
The fastest way will be this:
function remove(array: Array, name: String): void {
var n: int = array.length
while(--n > -1) {
if(name == array[n].name) {
array.splice(n, 1)
return
}
}
}
remove([{name: "hi"}], "hi")
You can also remove the return statement if you want to get rid of all alements that match the given predicate.
Upvotes: 5
Reputation: 2545
If you are willing to spend some memory on a lookup table this will be pretty fast:
private function remove( data:Array, objectTable:Object, name:String):void {
var index:int = data.indexOf( objectTable[name] );
objectTable[name] = null;
data.splice( index, 1 );
}
The test for this looks like this:
private function test():void{
var lookup:Object = {};
var Spokes:Array = [];
for ( var i:int = 0; i < 1000; i++ )
{
var obj:Object = { name: (Math.random()*0xffffff).toString(16), someOtherProperty:"blah" };
if ( lookup[ obj.name ] == null )
{
lookup[ obj.name ] = obj;
Spokes.push( obj );
}
}
var t:int = getTimer();
for ( var i:int = 0; i < 500; i++ )
{
var test:Object = Spokes[int(Math.random()*Spokes.length)];
remove(Spokes,lookup,test.name)
}
trace( getTimer() - t );
}
Upvotes: 12
Reputation: 11
You could also use ArrayCollection with a filterFunction to get a view into the same Array object
Upvotes: 0
Reputation: 29433
I don't have data to back it up but my guess is that array.filter might be the fastest.
Upvotes: 1
Reputation: 31883
If you don't mind using the ArrayCollection, which is a wrapper for the Array class, you could do something like this:
private function RemoveSpoke(Name:String, Spokes:Array):Array{
var ac:ArrayCollection = new ArrayCollection(Spokes);
for (var i:int=0, imax:int=ac.length; i<imax; i++) {
if (Spokes[i].hasOwnProperty("Name") && Spokes[i].Name === Name) {
ac.removeItemAt(i);
return ac.source;
}
}
return ac.source;
}
Upvotes: 0