2010-05-26 8 views
6

I tiene una matriz de objetos. Cada objeto tiene una propiedad llamada nombre. Quiero eliminar de manera eficiente un objeto con un nombre particular de la matriz. ¿Es esta la mejor manera?manera más eficiente para eliminar un elemento de una matriz en Actionscript 3

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; 
    } 

Respuesta

12

Si usted está dispuesto a gastar algo de memoria en una tabla de búsqueda esto será bastante rápido:

private function remove(data:Array, objectTable:Object, name:String):void { 
var index:int = data.indexOf(objectTable[name]); 
objectTable[name] = null; 
data.splice(index, 1); 
} 

la prueba de esto se parece a esto:

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); 

}

+0

Una cosa importante acerca de esta solución: solo funcionará si cada "nombre" es único. Si hay varios objetos con el mismo nombre, la tabla de búsqueda fallará, al menos si está construida de esta manera. – Quasimondo

+0

interesante ... por lo que básicamente tiene dos listas con datos duplicados ... en general, ¿sería mejor usar tablas de búsqueda y prescindir de matrices para estas situaciones? ¿Funciona esto solo porque el objeto tiene una propiedad 'name' o el método' indexOf' busca en cada valor de propiedad del objeto? – mga

+0

Sí, si no necesita la matriz para otros fines (como ordenar o acceder a los elementos por índice) en este caso, puede usar la tabla de búsqueda. indexOf encuentra instancias de un objeto. En este caso, no usa "nombre" para la comparación. El nombre se usa como hash en la tabla de búsqueda. – Quasimondo

0

Si no les importa usar el ArrayCollection, que es un contenedor para la clase Array, se podría hacer algo como esto:

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; 
} 
+0

FYI ArrayCollection sólo está disponible en Flex – Quasimondo

+1

@Quasimondo: FYI Flex es una de las etiquetas sobre la cuestión. – Robusto

+0

Oh cierto, lo extrañé totalmente. – Quasimondo

1

no tengo datos para respaldarlo pero mi suposición es que array.filter podría ser el más rápido.

+1

Si quiere decir algo como esto: var filterName: String = "algo"; Radios = Spokes.filter (función (elemento: *, index: int, arr: Array): Boolean { \t retorno (element.name = filterName);!}); entonces debo decepcionarte. Es aproximadamente 5 veces más lento que Joa y casi 30 veces más lento que el mío. – Quasimondo

+0

Haha. Ustedes, ¡hagan trampa! ;) ¿Array.filter es al menos el más rápido para los métodos basados ​​en bucle/iterador? –

5

La forma más rápida será la siguiente:

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") 

También puede quitar la instrucción de retorno si usted quiere deshacerse de todos los alements que coinciden con el predicado dado.

+0

Joa! Tu rock Pero, ¿podrá Apparat hacerlo aún más rápido?:) –

+7

Me permití comparar tu "más rápido" contra el mío y tener malas noticias: eliminar 500 elementos de una matriz de 1000 elementos: los tuyos 34 ms, los míos 4ms ;-) – Quasimondo

0

También es posible usar ArrayCollection con un filterFunction para obtener una visión en el mismo objeto Array

0

Él es una función eficiente en términos de reusabilidad, que le permite hacer más que quitar el elemento. Devuelve el índice, o -1 si no se encuentra.

 
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; 
} 
+0

Parece que el formateo eliminó el tipo de vector, pero supongo que es "Objeto". Lo probé rápidamente y al menos para mí usar Vector en este caso es realmente más lento. Creo que si quieres sacar provecho de la velocidad de Vector, también deberías usar un tipo real y no un "Objeto". – Quasimondo

+0

Gracias Cuasi. ¿Has probado usando mi función? Tiene un valor condicional adicional (hasOwnProperty) que lo ralentizaría pero tendría sentido si no está seguro de que el objeto tendrá la propiedad. Para hacerlo más rápido eliminar eso. Pero el usuario preguntó acerca de la eficiencia, y esta función habla de eso en términos de reutilización. – reelfernandes

+0

Lo probé con la propuesta de Joa, por lo que el hasOwnProperty no fue el problema aquí. – Quasimondo

1

En general se debe preferir el viejo ciclo for over "para cada" y "para cada uno" y use Vector si sus elementos son del mismo tipo. Si el rendimiento es realmente importante, debería considerar usar una lista vinculada.

Salida de Grant Skinner se desliza http://gskinner.com/talks/quick/ y Blog de Jackson Dunstan para mas informaciones sobre la optimización.

10

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

Cuestiones relacionadas