webentwicklung-frage-antwort-db.com.de

Gibt es eine Möglichkeit, ein Wörterbuch zu durchlaufen?

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?

195
HelloMoon

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]);
313
Adam Rosenfield

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.

149
Rok Strniša

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.