2010-05-26 2 views

Répondre

12

Si vous êtes prêt à passer un peu de mémoire sur une table de recherche ce sera assez rapide:

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

le test pour cela ressemble à ceci:

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

Une chose importante à propos de cette solution: ça marchera si chaque "nom" est unique. S'il y a plusieurs objets avec le même nom, la table de recherche échouera, au moins si elle est construite comme ceci. – Quasimondo

+0

intéressant ... donc vous avez essentiellement deux listes avec des données en double ... en général serait-il préférable d'utiliser simplement des tables de recherche et de se passer de tableaux pour ces situations? cela fonctionne-t-il simplement parce que l'objet a une propriété 'name' ou que la méthode' indexOf' recherche dans chaque valeur de propriété de l'objet? – mga

+0

Oui, si vous n'avez pas besoin du tableau à d'autres fins (comme le tri ou l'accès aux éléments par index), dans ce cas, vous pouvez simplement utiliser la table de recherche. indexOf trouve des instances d'un objet. Dans ce cas, il n'utilise pas du tout "nom" pour la comparaison. Le nom est utilisé comme hachage dans la table de recherche. – Quasimondo

0

Si vous ne me dérange pas à l'aide du ArrayCollection, qui est une enveloppe pour la classe Array, vous pouvez faire quelque chose comme ceci:

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 est uniquement disponible dans Flex – Quasimondo

+1

@Quasimondo: FYI Flex est l'un des tags de la question. – Robusto

+0

Oh vrai, j'ai totalement raté celui-là. – Quasimondo

1

Je n'ai pas de données pour le sauvegarder mais je suppose que array.filter pourrait être le plus rapide.

+1

Si vous voulez dire quelque chose comme ceci: var filterName: String = "something"; Spokes = Spokes.filter (function (element: *, index: int, arr: tableau): Boolean { \t return (element.name! = FilterName);}); alors je dois vous décevoir. C'est environ 5 fois plus lent que Joa et presque 30 fois plus lent que le mien. – Quasimondo

+0

Haha. Vous trichez les gars! ;) Array.filter est-il au moins le plus rapide pour les méthodes basées sur la boucle/l'itérateur? –

5

La façon la plus rapide sera la suivante:

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

Vous pouvez également supprimer l'instruction de retour si vous voulez vous débarrasser de tous les alements qui correspondent au prédicat donné.

+0

Joa! Tu gères. Mais Apparat sera-t-il capable de le rendre encore plus rapide?:) –

+7

Je me suis permis de comparer votre "plus rapide" contre le mien et venir avec de mauvaises nouvelles: enlever 500 éléments d'un tableau 1000 éléments - le vôtre 34 ms, le mien 4ms ;-) – Quasimondo

0

Vous pouvez également utiliser ArrayCollection avec un filterFunction pour obtenir une vue dans le même objet Array

0

Il C'est une fonction efficace en termes de réutilisabilité, vous permettant de faire plus que de supprimer l'élément. Il renvoie l'index, ou -1 s'il n'est pas trouvé.

 
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

On dirait que le formatage a supprimé le type de votre vecteur, mais je suppose que c'est "Objet". Je l'ai testé rapidement et au moins pour moi en utilisant Vector dans ce cas est en fait plus lent. Je pense que si vous voulez profiter de la vitesse de Vector, vous devez également utiliser un type réel et non "Object". – Quasimondo

+0

Merci Quasi. Avez-vous testé en utilisant ma fonction? Il a ajouté un conditionnel (hasOwnProperty) qui le ralentirait mais aurait du sens si vous n'êtes pas sûr que l'objet aura la propriété. Pour le rendre plus rapide, supprimez cela. Mais l'utilisateur a posé des questions sur l'efficacité, et cette fonction répond à cela en termes de réutilisabilité. – reelfernandes

+0

Je l'ai testé avec la proposition de Joa, donc le hasOwnProperty n'était pas le problème ici. – Quasimondo

1

En général, vous devriez préférer le vieux pour en boucle sur « pour chaque » et "pour chaque" et utilisez Vector si vos éléments sont du même type. Si la performance est vraiment importante, vous devriez envisager d'utiliser une liste chaînée.

Consultez les diapositives Grant Skinners http://gskinner.com/talks/quick/ et le blog de Jackson Dunstan pour plus d'informations sur l'optimisation.

10

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

Questions connexes