Joshua
Joshua

Reputation: 6843

More efficient way to remove an element from an array in Actionscript 3

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

Answers (9)

LeManu
LeManu

Reputation: 101

myArray.splice(myArray.indexOf(myInstance), 1);

Upvotes: 10

reelfernandes
reelfernandes

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

DieTapete
DieTapete

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

user77838
user77838

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

Joa Ebert
Joa Ebert

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

Quasimondo
Quasimondo

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

simms2k
simms2k

Reputation: 11

You could also use ArrayCollection with a filterFunction to get a view into the same Array object

Upvotes: 0

James Ward
James Ward

Reputation: 29433

I don't have data to back it up but my guess is that array.filter might be the fastest.

Upvotes: 1

Robusto
Robusto

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

Related Questions