Apakah ada cara untuk beralih ke kamus?

200

Saya tahu NSDictionariessebagai sesuatu di mana Anda membutuhkan keyuntuk mendapatkan value. Tetapi bagaimana saya bisa mengulangi semua keysdan valuesdalam NSDictionary, sehingga saya tahu kunci apa yang ada, dan nilai apa yang ada? Saya tahu ada sesuatu yang disebut for-in-loop in JavaScript. Apakah ada sesuatu yang serupa Objective-C?

Alex Cio
sumber
Terima kasih untuk posting ini. Jika iterating dalam Swiftsintaks, lihat posting ini: stackoverflow.com/a/24111700/419348
AechoLiu

Jawaban:

323

Ya, NSDictionarymendukung penghitungan cepat. Dengan Objective-C 2.0, Anda dapat melakukan ini:

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

Metode alternatif (yang harus Anda gunakan jika Anda menargetkan Mac OS X pra-10.5, tetapi Anda masih bisa menggunakan pada 10.5 dan iPhone) adalah dengan menggunakan 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]);
Adam Rosenfield
sumber
2
Sintaks modern ObjC: NSLog (@ "key =% @ value =% @", key, myDict [key]);
geowar
@Darthenius karena optimasi baru-baru ini, penghitungan cepat sekali lagi lebih cepat daripada berbasis blok, setidaknya dalam kasus-kasus tertentu. Tetapi jika masalah yang Anda selesaikan memungkinkan Anda untuk menggunakan opsi bersamaan, pendekatan berbasis blok mungkin lebih cepat.
Zev Eisenberg
@ZevEisenberg Lihat akhir posting saya.
Rok Strniša
Ups, saya mengklik tautan Anda, di atas, untuk membuka di tab baru, dan bahkan tidak memperhatikan siapa yang menulisnya atau itu ada di halaman yang sama. Jika Anda masih dapat mengedit komentar di atas, Anda mungkin ingin, sehingga pembaca yang malas tidak mendapatkan ide yang salah.
Zev Eisenberg
153

Pendekatan blok menghindari menjalankan algoritma pencarian untuk setiap kunci :

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

Meskipun NSDictionarydiimplementasikan sebagai hashtable (yang berarti bahwa biaya mencari elemen adalah O(1)), pencarian masih memperlambat iterasi Anda dengan faktor konstan .

Pengukuran saya menunjukkan bahwa untuk kamus dangka ...

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

... merangkum angka-angka dengan pendekatan blok ...

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

... daripada pendekatan loop ...

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

... sekitar 40% lebih cepat .

EDIT : SDK baru (6.1+) muncul untuk mengoptimalkan iterasi loop, sehingga pendekatan loop sekarang sekitar 20% lebih cepat daripada pendekatan blok , setidaknya untuk kasus sederhana di atas.

Rok Strniša
sumber
Bagaimana dengan iOS 10/11, mana yang lebih cepat?
Supertecnoboff
elegan, cinta itu!
YvesLeBorg
10

Ini adalah iterasi menggunakan pendekatan blok:

    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.
    }];

Dengan pelengkapan otomatis sangat cepat untuk diatur, dan Anda tidak perlu khawatir menulis amplop iterasi.

Javier Calatrava Llavería
sumber
Terima kasih .. Solusi yang bagus jika Anda perlu bermutasi NSMutableDictionary dalam proses
jose920405