Ich kenne NSDictionaries
als etwas, wo Sie ein key
benötigen, um ein value
zu erhalten. Aber wie kann ich alle keys
und values
in einem NSDictionary
durchlaufen, damit ich weiß, welche Schlüssel es gibt und welche Werte es gibt? Ich weiß, dass es in JavaScript
etwas gibt, das for-in-loop heißt. Gibt es etwas Ähnliches in Objective-C
?
Ja, NSDictionary
unterstützt die schnelle Aufzählung. Mit Objective-C 2.0 können Sie Folgendes tun:
// To print out all key-value pairs in the NSDictionary myDict
for(id key in myDict)
NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]);
Die alternative Methode (die Sie verwenden müssen, wenn Sie auf Mac OS X vor 10.5 abzielen, aber weiterhin auf 10.5 und iPhone verwenden können) ist die Verwendung eines 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]);
Der Blockansatz vermeidet das Ausführen des Suchalgorithmus für jeden Schlüssel:
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
NSLog(@"%@ => %@", key, value);
}];
Obwohl NSDictionary
als Hash-Tabelle implementiert ist (was bedeutet, dass die Kosten für das Nachschlagen eines Elements O(1)
betragen) ), Lookups verlangsamen Ihre Iteration immer noch um einen konstanten Faktor.
Meine Messungen zeigen, dass für ein Wörterbuch d
von Zahlen ...
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
for (int i = 0; i < 5000000; ++i) {
NSNumber* value = @(i);
dict[value.stringValue] = value;
}
... die Zahlen mit dem Blockansatz zusammenfassen ...
__block int sum = 0;
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber* value, BOOL* stop) {
sum += value.intValue;
}];
... eher als der Loop-Ansatz ...
int sum = 0;
for (NSString* key in dict)
sum += [dict[key] intValue];
... ist ungefähr 40% schneller .
[~ # ~] edit [~ # ~] : Das neue SDK (6.1+) scheint die Schleifeniteration zu optimieren, daher ist der Schleifenansatz jetzt Etwa 20% schneller als die Blockannäherung , zumindest für den oben beschriebenen einfachen Fall.
Dies ist die Iteration unter Verwendung des Blockansatzes:
NSDictionary *dict = @{@"key1":@1, @"key2":@2, @"key3":@3};
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"%@->%@",key,obj);
// Set stop to YES when you wanted to break the iteration.
}];
Mit Autovervollständigung lässt sich sehr schnell einstellen, und Sie müssen sich nicht um das Schreiben des Iterationsumschlags kümmern.