Znam NSDictionaries
jako coś, czego potrzebujesz key
, aby uzyskać value
. Ale jak mogę iterować po wszystkich keys
i values
w NSDictionary
, tak że wiem, jakie są klucze i jakie są wartości? Wiem, że jest coś o nazwie dla pętli w pętli w JavaScript
. Czy jest coś podobnego w Objective-C
?Czy istnieje sposób do iteracji w słowniku?
Odpowiedz
Tak, NSDictionary
obsługuje szybkie wyliczanie. Z Objective-C 2.0, można to zrobić:
// To print out all key-value pairs in the NSDictionary myDict
for(id key in myDict)
NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]);
Sposób alternatywny (które trzeba użyć, jeśli jesteś kierowania Mac OS X 10.5 wstępnie, ale nadal można używać na 10,5 i iPhone) jest aby użyć 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]);
podejście blok unika działa algorytm odnośnika do każdy klucz:
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
NSLog(@"%@ => %@", key, value);
}];
Mimo że NSDictionary
jest zaimplementowany jako hashtable (co oznacza, że koszt wyszukiwania elementu wynosi O(1)
), wyszukiwania wciąż spowalniają twoją iterację przez stały współczynnik.
Moje pomiary pokazują, że do słownika d
liczb ...
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
for (int i = 0; i < 5000000; ++i) {
NSNumber* value = @(i);
dict[value.stringValue] = value;
}
... zsumowaniu cyfr z podejściem bloku ...
__block int sum = 0;
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber* value, BOOL* stop) {
sum += value.intValue;
}];
... zamiast podejście pętli ...
int sum = 0;
for (NSString* key in dict)
sum += [dict[key] intValue];
... jest ab obecnie o 40% szybszy.
EDIT: Nowy SDK (6.1+) wydaje się optymalizacji iteracji, tak podejście pętli jest o 20% krótszy niż podejście modułowe, przynajmniej dla prostego przypadku powyżej.
A co z systemem iOS 10/11, który z nich jest szybszy? – Supertecnoboff
elegancki, uwielbiam to! – YvesLeBorg
to iteracja stosując podejście bloku:
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.
}];
Z autouzupełniania jest bardzo szybkie ustawianie, i nie trzeba się martwić o pisanie iteracji kopertę.
Dzięki .. Dobre rozwiązanie, jeśli potrzebujesz zmutować 'NSMutableDictionary' w procesie – jose920405
Podejście blokowe jest szybsze. Zobacz http://stackoverflow.com/a/12454766/974531. –
Nowoczesna składnia ObjC: NSLog (@ "key =% @ value =% @", key, myDict [key]); – geowar
@Darthenius ze względu na ostatnie optymalizacje, szybkie wyliczanie jest ponownie szybsze niż oparte na blokach, przynajmniej w niektórych przypadkach. Ale jeśli problem, który rozwiązujesz, pozwala korzystać z opcji współbieżnej, podejście blokowe może być szybsze. –