¿Hay una manera de iterar sobre un diccionario?
Conozco NSDictionaries
como algo donde necesitas un key
para obtener un value
. Pero ¿cómo puedo iterar sobre todos keys
y values
en un NSDictionary
, para saber qué claves hay, y qué valores hay? Sé que hay algo llamado for-in-loop en JavaScript
. Hay algo similar en Objective-C
?
3 answers
Sí, NSDictionary
admite la enumeración rápida. Con Objective-C 2.0, puedes hacer esto:
// To print out all key-value pairs in the NSDictionary myDict
for(id key in myDict)
NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]);
El método alternativo (que debe usar si está apuntando a Mac OS X pre-10.5, pero aún puede usar en 10.5 y iPhone) es usar un 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]);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-16 15:27:08
El enfoque de bloque evita ejecutar el algoritmo de búsqueda para cada clave :
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
NSLog(@"%@ => %@", key, value);
}];
Aunque NSDictionary
se implementa como una hashtable (lo que significa que el costo de buscar un elemento es O(1)
), las búsquedas todavía ralentizan su iteración por un factor constante.
Mis mediciones muestran que para un diccionario d
de números ...
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
for (int i = 0; i < 5000000; ++i) {
NSNumber* value = @(i);
dict[value.stringValue] = value;
}
... resumiendo los números con el enfoque de bloque ...
__block int sum = 0;
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber* value, BOOL* stop) {
sum += value.intValue;
}];
... en lugar del enfoque de bucle ...
int sum = 0;
for (NSString* key in dict)
sum += [dict[key] intValue];
... es aproximadamente un 40% más rápido.
EDITAR : El nuevo SDK (6.1+) parece optimizar la iteración de bucle, por lo que el enfoque de bucle ahora es aproximadamente un 20% más rápido que el enfoque de bloque, al menos para el caso simple anterior.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-12 20:38:35
Esta es la iteración usando el enfoque de bloque:
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.
}];
Con autocompletado es muy rápido de configurar, y no tiene que preocuparse por escribir sobre iteración.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-28 06:41:49