Croiser 2 arrays de dictionnaires
muqaddar
Administrateur
Salut,
Est-ce que quelqu'un a une astuce pour croiser 2 arrays de dictionnaires afin de vérifier l'équivalence de valeurs de clés ?
Exemple :
array1 contient 100 dictionnaires de 2 clés/valeurs (x, y)
array2 contient 10 dictionnaires de 2 clés/valeurs (x, y)
On veut vérifier que (array1.x == array2.x et array1.y == array2.y).
On peut énumérer array1 et énumérer array2 à l'intérieur et comparer les valeurs des clés...
Seulement, bonjour les perfs je pense...
Peut-être créer 2 tableaux temporaires pour comparer autrement (containsObject ?) ? Afin de récupérer un index dans le tableau original.
Vos suggestions sont les bienvenues.
Est-ce que quelqu'un a une astuce pour croiser 2 arrays de dictionnaires afin de vérifier l'équivalence de valeurs de clés ?
Exemple :
array1 contient 100 dictionnaires de 2 clés/valeurs (x, y)
array2 contient 10 dictionnaires de 2 clés/valeurs (x, y)
On veut vérifier que (array1.x == array2.x et array1.y == array2.y).
On peut énumérer array1 et énumérer array2 à l'intérieur et comparer les valeurs des clés...
Seulement, bonjour les perfs je pense...
Peut-être créer 2 tableaux temporaires pour comparer autrement (containsObject ?) ? Afin de récupérer un index dans le tableau original.
Vos suggestions sont les bienvenues.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Ok, je vais essayer. Je me sers rarement des NSSet.
D'accord c'est toujours parcourir mais en général les blocks ça va plutôt très vite ..
hth
Si tu me dis que les objets qu'il y a dans tes NSArray (en l'occurrence tes NSDictionary (x,y)) ne sont pas directement comparables par isEqual car en fait n'ont pas la même structure, là c'est autre chose.
Mais si tu as un NSArray a avec 20 paires (x,y) et un NSArray b avec 12 paires (x,y) dont certaines communes avec le tableau a, alors NSSet va bien te permettre de faire cela.
Si c'est pas le cas, alors j'ai mal compris ton problème (et un exemple serait alors le bienvenu)
Je plussoie.
Voilà , c'est ça... ;-) Les dico ne sont pas les mêmes.
D'un côté j'ai des dico à 3 clés/valeurs.
De l'autre des dicos à 10 clés/valeurs.
Je veux comparer seulement 1 paire de clé/valeurs entre les 2 arrays.
Appellons-les X,Y. Ce sont des NSNumber dans les dicos.
Dans mon cas précis, je parcoure un array1 (et dans tous les cas, celui-là , j'ai besoin de le parcourir dans mon code pour d'autres besoins). Je lui prends d'ailleurs X et Y au moment de son énumération. Disons que cet array possède 100 dicos.
Pour des questions de performance, je ne souhaite pas faire une énumération du deuxième array dans chaque itération du premier array avec objectEnumerator. Certes le nombre d'éléments est dérisoire avec mon exemple, mais avec des doubles boucles, on arrive vite à 10000 itérations.
Les blocks sont peut-être une piste de performance comme l'a dit laudema.
Les blocks, ce sont des closures. Ca n'a aucun impact sur les performances.
Par contre, utiliser GCD ou les NSFastEnumerations (qui utilisent en général les blocks dans leur API pour manipuler plus facilement ces énumérations) c'est autre chose.
GCD va te permettre d'exécuter des bouts de code (que tu passes effectivement en paramètre via des blocks) éventuellement en parallèle.
Les NSFastEnumerations vont permettre de récupérer (dans tes énumérations par boucle for avec la syntaxe NSFastEnumeration) les éléments de ton tableau morceaux par morceaux (genre 5 par 5 ou quoi) sous le capot, même si ensuite chaque élément est énuméré un par un (en gros sous le capot ça récupère le N premiers d'un bloc, puis itère sur ces N éléments, puis récupère les pointeurs vers les N suivants, etc... au lieu de récupérer le 1er, le traiter, récupérer le 2e, le traiter, etc) ce qui accélère un peu les boucles dans les faits.
Dans les deux si tes tableau ne contiennent pas des objets de même structure tu vas avoir à itérer dans tes tableau de toute façon Ou éventuellement dériver de ton tableau de dicos à 10 clés un tableau de dicos à 2 clés avec la même structure que l'autre tableau, et faire le filtrage avec ce tableau dérivé (où là tu pourras comparer les dicos entre un tableau et l'autre), mais bon...
Au final je me demande si ton archi et ta structure de données est bien choisie...
ça fait un peu chier que ça soit des simples NSDictionary.. mais si tu as la "main" dessus, ça serait plus intéressant de combiner les valeurs de X et Y à une seule clé.
Sinon, @unionOfObjects est ultra rapide de toute manière.
Sinon, comme laudema, je serai curieux de voir les perfs avec des blocks..
Edit: j'ai fait un test avec un de mes projet actuel, le -enumerateObjectsWithOptions:usingBlock: est plus lent qu'une fast énumération.
Après, je suppose que ça doit dépendre de la taille de la array (j'en suis à 5000 éléments)
À noter que je faisais une simple énumération de mon côté par contre..
0.023s avec la méthode utilisant le block
0.020s avec une fast enum.
(Sur OS X... donc à tester aussi sur iOS.)
Ma array contient + de 5000 éléments, qui sont des dictionnaires. Chaque dico contient plusieurs clés. J'ai testé la récupération des valeurs pour la clé "album", ça met 0.003s sur OS X.
Maintenant, j'ai testé @unionOfObjects sur 4 clés:
J'en ai pour 0.007s
Faisons la même chose, en récupérant les albums, artists, names, et genres dans une fastenum. On se dit que ça va être plus rapide vu qu'on énumère une fois. Alors que ci-dessus on répète @unionOfObjects 4x! Totalement logique effectivement, ça met 0.003s, soit autant de temps qu'un seul @unionOfObjects.
ça n'est donc p-e pas la meilleure solution. Mais ça dépend vraiment de la taille de ta array. Si c'est assez "petit", je pense que tu peux te simplifier la vie en faisant ça.
Vous utilisez quoi comme fonctions pour mesurez les benches au miliseconde ?
Moi j'instancie une NSDate avant exécution et je log le timeIntervalSinceDate: après
Si vous avez mieux je suis carrément preneur!
C'est le même principe quoi..
Quand on fait du benchmark, si on commence à polluer le benchmark par des allocations (alloc/init d'un NSDate, même si ça dure pas 10s c'est pas gratuit non plus) c'est pas comme ça que t'auras des résultats de bench exploitables
Sinon t'as l'utilitaire "time" en ligne de commande pour benchmarker le temps d'exécution d'un process du début à la fin.
T'as pas tort..
Je vais essayer plusieurs pistes, mais à ce stade de mon appli je n'ai pas encore assez d'éléments dans mes arrays pour faire des benches crédibles. A suivre dans quelque temps.