86 votes

Existe-t-il un moyen d'itérer sur un dictionnaire ?

Je connais les dictionnaires comme quelque chose où il faut une clé pour obtenir une valeur. Mais comment puis-je itérer sur toutes les clés et valeurs d'un dictionnaire, afin de savoir quelles clés et quelles valeurs il contient ? Je sais qu'il existe un élément appelé pour-en-boucle en JavaScript. Existe-t-il quelque chose de similaire en Objective-C ?

151voto

Adam Rosenfield Points 176408

Oui, NSDictionary supporte l'énumération rapide. Avec Objective-C 2.0, vous pouvez le faire :

// To print out all key-value pairs in the NSDictionary myDict
for(id key in myDict)
    NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]);

L'autre méthode (que vous devez utiliser si vous ciblez Mac OS X pré-10.5, mais que vous pouvez toujours utiliser sur 10.5 et iPhone) consiste à utiliser un fichier de type NSEnumerator :

NSEnumerator *enumerator = [myDict keyEnumerator];
id key;
// extra parens to suppress warning about using = instead of ==
while((key = [enumerator nextObject]))
    NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]);

68voto

Darthenius Points 1828

L'approche par blocs évite d'exécuter l'algorithme de recherche pour chaque clé :

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
  NSLog(@"%@ => %@", key, value);
}];

Même si NSDictionary est mis en œuvre comme un table de hachage (ce qui veut dire que le coût de recherche d'un élément est de O(1) ), les recherches ralentissent toujours votre itération en un facteur constant .

Mes mesures montrent que pour un dictionnaire d de chiffres ...

NSMutableDictionary* dict = [NSMutableDictionary dictionary];
for (int i = 0; i < 5000000; ++i) {
  NSNumber* value = @(i);
  dict[value.stringValue] = value;
}

... en résumant les chiffres avec l'approche par blocs ...

__block int sum = 0;
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber* value, BOOL* stop) {
  sum += value.intValue;
}];

... plutôt que l'approche en boucle ...

int sum = 0;
for (NSString* key in dict)
  sum += [dict[key] intValue];

... est environ 40% plus rapide .

EDIT : Le nouveau SDK (6.1+) semble optimiser l'itération de boucle, donc l'approche en boucle est maintenant environ 20% plus rapide que l'approche en bloc du moins pour le cas simple ci-dessus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X