2013-06-21 3 views
1

Supposons que nous ayons un certain type d'objet personnalisé:algorithme efficace pour trouver des objets de valeur dans la collecte

class SomeObjectType { 
    public var intProperty1:int; 
    public var intProperty2:int; 
    public var intProperty3:int; 
    public var stringProperty1:String; 
    public var stringProperty2:String; 
    public var stringProperty3:String; 
    public var stringPropertyThatActuallyIsInt1:String; 
    public var stringPropertyThatActuallyIsInt2:String; 
    public var stringPropertyThatActuallyIsInt3:String; 
    ... 
    %ABOUT_20_ANOTHER_PROPERTIES_THAT_I_WON'T_USE% 
} 

Nous avons une collection de plus de 20k instances de ces objets. Et nous avons juste 1 entrée de texte qui est en fait un filtre de recherche. L'utilisateur peut taper dans ce champ tout ce qu'il veut et si son filtre correspond à N'IMPORTE QUEL des 9 premiers champs que j'ai décrits avant, nous devrions laisser cet objet dans la collection. Juste le filtrage des éléments simples.

Et permettez-moi de décrire comment cela fonctionne dans notre projet maintenant. Cet algorithme convertit toutes ces propriétés en chaînes, les concatène et effectue une recherche en utilisant la méthode indexOf()! = -1. C'est vraiment lent. Il faut environ 500-900ms sur ma machine dev et environ 3-4s sur iPad à chaque changement de filtre. Statistiques horribles, n'est-ce pas?

Petite note: nous utilisons cet algorithme à différents endroits de l'application et les objets diffèrent de l'objet I décrit plus haut mais l'idée est la même. Je crois que c'est une bonne idée de comparer int à int, string à string (implémentant quelques algorithmes rapides (il y en a beaucoup)), et convertir une chaîne qui est réellement en int et les comparer en int à int, mais object diffère beaucoup donc j'ai besoin d'un algorithme commun.

Répondre

2

Si par collection vous entendez ArrayCollection, je recommanderais d'utiliser Vector à la place.

Les vecteurs sont environ 50 fois plus rapides que ArrayCollections.

Si vous avez besoin d'une liaison de données, vous pouvez jeter un oeil à VectorCollection, mais je ne peux pas imaginer que les performances soient proches de Vector.

De plus, si vous ne développez pas de classe SomeObjectType n'importe où, vous pouvez obtenir des performances (en particulier sur iOS) en faisant de la classe finale SomeObjectType.

+0

Merci pour des conseils pour faire de la classe finale. Je vais essayer de l'utiliser demain. Vous avez raison à propos de ArrayCollection - nous les utilisons. Mais nous ne pouvons pas changer ArrayCollection en Vector, car Adobe ADEP l'utilise uniquement comme ArrayCollection. Je ne pense pas que la conversion de ArrayCollection à (nouveau!) Vector aidera avec la performance – shvetsroman

+0

@murdoc Pourquoi? -> "Je ne pense pas que la conversion de ArrayCollection en (nouveau!) Vecteur aidera avec la performance". Vous pouvez faire une copie de votre collection dans un vecteur et lancer un test. –

+0

Jetez également un oeil à la réponse ici: http://stackoverflow.com/questions/2672096/arraycollection-versus-vector-objects-in-flex –

0

Vous pouvez utiliser le dictionnaire pour effectuer une recherche, je pense que ce sera beaucoup plus rapide, vous avez juste besoin d'init pour une fois.

var dict:Dictionary = new Dictionary(); 

//get properties,in you obj, they are intProperty1,intProperty2 etc,exclude prototype 
var properties:Array = ObjectUtil.getClassInfo(SomeObjectType, ["prototype"]).properties as Array; 

for each (var obj:SomeObjectType in yourArrayCollection) { 

    for (var i:int = 0; i < properties.length; i++) { 

     var qname:Object = properties[i]; 
     var k:String = qname.localName; 

     var v:String = obj[k]; 

     if (dict[v] == null) { 
      dict[v] = []; 
     } 

     //add only one time 
     if ((dict[v] as Array).indexOf(obj) == -1) { 
      (dict[v] as Array).push(obj); 
     } 
    } 

} 

Donc, si vous voulez retourner tous les obj contient « 5 », juste revenir dict [5]

Questions connexes