Я знаю NSDictionaries
как то, где вам нужен key
, чтобы получить value
. Но как я могу перебирать все keys
и values
в NSDictionary
, чтобы я знал, какие ключи есть и какие значения есть? Я знаю, что есть что-то, называемое for-in-loop в JavaScript
. Есть ли что-то подобное в Objective-C
?
Есть ли способ перебора словаря?
Ответ 1
Да, NSDictionary
поддерживает быстрое перечисление. С помощью Objective-C 2.0 вы можете сделать это:
// To print out all key-value pairs in the NSDictionary myDict
for(id key in myDict)
NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]);
Альтернативный метод (который вы должны использовать, если вы ориентируетесь на Mac OS X до 10.5, но вы все еще можете использовать на 10.5 и iPhone) заключается в использовании 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]);
Ответ 2
Блочный подход позволяет избежать выполнения алгоритма поиска для каждого ключа:
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
NSLog(@"%@ => %@", key, value);
}];
Несмотря на то, что NSDictionary
реализован как hashtable (это означает, что стоимость поиск элемента O(1)
), поисковые запросы по-прежнему замедляют вашу итерацию на постоянный коэффициент.
Мои измерения показывают, что для словаря d
чисел...
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
for (int i = 0; i < 5000000; ++i) {
NSNumber* value = @(i);
dict[value.stringValue] = value;
}
... суммируя числа с блочным подходом...
__block int sum = 0;
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber* value, BOOL* stop) {
sum += value.intValue;
}];
... а не петлевой подход...
int sum = 0;
for (NSString* key in dict)
sum += [dict[key] intValue];
... примерно на 40% быстрее.
EDIT. Новый SDK (6.1+), по-видимому, оптимизирует итерацию цикла, поэтому подход к петле теперь примерно на 20% быстрее, чем блок-подход, по крайней мере для простой пример выше.
Ответ 3
Это итерация с использованием блочного подхода:
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.
}];
С автозаполнением очень быстро устанавливается, и вам не нужно беспокоиться о записи итерационного конверта.