มีวิธีการทำซ้ำในพจนานุกรมหรือไม่?


200

ฉันรู้ว่าNSDictionariesเป็นสิ่งที่คุณต้องการในการสั่งซื้อที่จะได้รับkey valueแต่ฉันจะทำซ้ำได้ทั้งหมดkeysและvaluesในNSDictionaryเพื่อที่ฉันจะรู้ว่ามีกุญแจอะไรและมีคุณค่าอะไรบ้าง? ฉันรู้ว่ามีสิ่งที่เรียกว่าสำหรับในวงJavaScriptใน มีอะไรที่คล้ายกันObjective-Cไหม?


ขอบคุณสำหรับโพสต์นี้ หากวนซ้ำในSwiftไวยากรณ์อ้างอิงโพสต์นี้: stackoverflow.com/a/24111700/419348
AechoLiu

คำตอบ:


323

ใช่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 pre-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
ไวยากรณ์ที่ทันสมัยของ ObjC: NSLog (@ "key =% @ value =% @", คีย์, myDict [key]);
geowar

@Darthenius เนื่องจากการเพิ่มประสิทธิภาพเมื่อเร็ว ๆ นี้การแจงนับที่รวดเร็วนั้นเร็วกว่าการใช้บล็อกเป็นอย่างน้อยในบางกรณี แต่หากปัญหาที่คุณแก้ไขช่วยให้คุณสามารถใช้ตัวเลือกที่เกิดขึ้นพร้อมกันวิธีการบล็อกตามอาจจะเร็วกว่า
Zev Eisenberg

@ZevEisenberg ดูจุดสิ้นสุดของโพสต์ของฉัน
Rok Strniša

โอ๊ะโอฉันคลิกที่ลิงก์ของคุณด้านบนเพื่อเปิดในแท็บใหม่และไม่ได้สังเกตว่าใครเป็นคนเขียนหรือมันอยู่ในหน้าเดียวกันนี้ หากคุณยังคงสามารถแก้ไขความคิดเห็นข้างต้นคุณอาจต้องการเพื่อให้ผู้อ่านที่ขี้เกียจไม่เข้าใจผิด
Zev Eisenberg

153

วิธีการบล็อกหลีกเลี่ยงการใช้อัลกอริทึมการค้นหาสำหรับทุกคีย์ :

[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%

แก้ไข : SDK ใหม่ (6.1+) จะปรากฏขึ้นเพื่อเพิ่มประสิทธิภาพการวนซ้ำวนซ้ำดังนั้นตอนนี้วิธีการวนรอบจะเร็วกว่าวิธีบล็อกประมาณ 20%อย่างน้อยสำหรับกรณีง่ายด้านบน


แล้ว iOS 10/11 แล้วอันไหนเร็วกว่ากัน?
Supertecnoboff

สง่างามรักมัน!
YvesLeBorg

10

นี่คือการวนซ้ำโดยใช้วิธีบล็อก:

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

ด้วยการเติมข้อความอัตโนมัตินั้นตั้งค่าได้รวดเร็วมากและคุณไม่ต้องกังวลกับการเขียนซองจดหมายซ้ำ


ขอบคุณ .. ทางออกที่ดีถ้าคุณต้องการกลายพันธุ์NSMutableDictionaryในกระบวนการ
jose920405
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.