C'è un modo per scorrere su un dizionario?


200

So NSDictionariescome qualcosa di cui hai bisogno keyper ottenere un value. Ma come posso iterare su tutto keyse valuesin un NSDictionary, in modo da sapere quali chiavi ci sono e quali valori ci sono? So che c'è qualcosa che si chiama un per-in-loop in JavaScript. C'è qualcosa di simile in Objective-C?


Grazie per questo post Se l'iterazione in Swiftsintassi, consultare questo post: stackoverflow.com/a/24111700/419348
AechoLiu

Risposte:


323

Sì, NSDictionarysupporta l'enumerazione rapida. Con Objective-C 2.0, puoi farlo:

// To print out all key-value pairs in the NSDictionary myDict
for(id key in myDict)
    NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]);

Il metodo alternativo (che devi utilizzare se scegli come target Mac OS X pre-10.5, ma puoi comunque utilizzare su 10.5 e iPhone) è utilizzare 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]);

2
Sintassi moderna di ObjC: NSLog (@ "chiave =% @ valore =% @", chiave, myDict [chiave]);
Geowar,

@Darthenius a causa delle recenti ottimizzazioni, l'enumerazione rapida è di nuovo più rapida di quella basata su blocchi, almeno in alcuni casi. Ma se il problema che stai risolvendo ti consente di usare l'opzione concorrente, l'approccio basato su blocchi potrebbe essere più veloce.
Zev Eisenberg,

@ZevEisenberg Vedi la fine del mio post.
Rok Strniša,

Spiacenti, ho fatto clic sul collegamento in alto per aprirlo in una nuova scheda e non ho nemmeno notato chi lo ha scritto o che si trovasse nella stessa pagina. Se riesci ancora a modificare il commento sopra, ti consigliamo di farlo, in modo che i lettori pigri non abbiano un'idea sbagliata.
Zev Eisenberg,

153

L'approccio a blocchi evita di eseguire l'algoritmo di ricerca per ogni tasto :

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
  NSLog(@"%@ => %@", key, value);
}];

Anche se NSDictionaryè implementato come hashtable (il che significa che il costo di cercare un elemento è O(1)), le ricerche rallentano ancora la tua iterazione di un fattore costante .

Le mie misurazioni mostrano che per un dizionario ddi numeri ...

NSMutableDictionary* dict = [NSMutableDictionary dictionary];
for (int i = 0; i < 5000000; ++i) {
  NSNumber* value = @(i);
  dict[value.stringValue] = value;
}

... riassumendo i numeri con l'approccio a blocchi ...

__block int sum = 0;
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber* value, BOOL* stop) {
  sum += value.intValue;
}];

... piuttosto che l'approccio loop ...

int sum = 0;
for (NSString* key in dict)
  sum += [dict[key] intValue];

... è circa il 40% più veloce .

EDIT : il nuovo SDK (6.1+) sembra ottimizzare l'iterazione di loop, quindi l'approccio di loop è ora circa il 20% più veloce dell'approccio di blocco , almeno per il semplice caso sopra.


Che dire di iOS 10/11, quale è più veloce?
Supertecnoboff

elegante, lo adoro!
YvesLeBorg,

10

Questa è iterazione usando l'approccio a blocchi:

    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 il completamento automatico è molto veloce da impostare e non devi preoccuparti di scrivere una busta di iterazione.


Grazie .. Buona soluzione se hai bisogno di mutare NSMutableDictionaryil processo
jose920405,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.