สำหรับแต่ละลูปใน Objective-C สำหรับการเข้าถึงพจนานุกรม NSMutable


268

ฉันพบปัญหาในการเข้าถึงคีย์และค่าพจนานุกรมที่ไม่แน่นอนใน Objective-C

สมมติว่าฉันมีสิ่งนี้:

NSMutableDictionary *xyz=[[NSMutableDictionary alloc] init];

ฉันสามารถตั้งค่าคีย์และค่าต่างๆ ตอนนี้ฉันต้องการเข้าถึงแต่ละคีย์และค่า แต่ฉันไม่ทราบจำนวนชุดของคีย์

ใน PHP มันง่ายมากมีดังนี้:

foreach ($xyz as $key => $value)

เป็นไปได้อย่างไรใน Objective-C

คำตอบ:


662
for (NSString* key in xyz) {
    id value = xyz[key];
    // do stuff
}

วิธีนี้ใช้ได้กับทุกคลาสที่สอดคล้องกับโปรโตคอล NSFastEnumeration (มีให้ใน 10.5+ และ iOS) แต่NSDictionaryเป็นหนึ่งในคอลเล็กชันบางส่วนที่ให้คุณระบุคีย์แทนค่าได้ ผมขอแนะนำให้คุณอ่านเกี่ยวกับการแจงนับรวดเร็วในคอลเลกชัน Programming กระทู้

โอ้ฉันควรเพิ่มอย่างไรก็ตามคุณไม่ควรแก้ไขคอลเลกชันในขณะที่ระบุผ่าน


4
ฉันสงสัยว่ามันไม่ควรจะเป็น: สำหรับ (รหัส NSString * ใน [xyz allKeys])? หรือมันไม่สำคัญ
FlowUI SimpleUITesting.com

6
@ user76859403 จริง ๆ แล้วการระบุพจนานุกรมในการระบุคีย์ for (NSString* key in [xyz allKeys])เป็นแนวคิดในสิ่งเดียวกัน
zneak

ใช้ [xyz allKeys] หากคุณจำเป็นต้องกลายพันธุ์พจนานุกรมในขณะที่แจกแจงคีย์ ดูคำตอบของฉันด้านล่าง
Brody Robertson

การวนซ้ำนี้กลับคำสั่งเดิมตลอดเวลาหรือไม่? หรือเราต้องการวิธีอื่นในการใช้งานสำหรับส่วนของ TableView
ymutlu

1
@ymutlu พจนานุกรมโกโก้ไม่มีการเรียงลำดับ ซึ่งหมายความว่าลำดับที่จะวนซ้ำอาจเปลี่ยนแปลงได้ทุกครั้งที่คุณแก้ไข
zneak

98

เพื่อไม่ให้เหลือตัวเลือก 10.6+ สำหรับการแจกแจงคีย์และค่าโดยใช้บล็อก ...

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

หากคุณต้องการให้การกระทำเกิดขึ้นพร้อมกัน:

[dict enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
                              usingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];

2
3 วิธีที่แตกต่างในการระบุผ่านพจนานุกรม . . เฮ้สิ่งนี้ทำให้ฉันนึกถึงคำตอบที่ "Strangest Language Feature" ซึ่ง VB มีลูปต่างกัน 7 แบบ
dreamlax

3
ดี ... objectEnumerator ถูกเพิ่มเข้ามาในปี 1994, สำหรับ (... ใน ... ) ในปี 2006 และบล็อกถูกเพิ่มเข้ามาในปี 2009 รูปแบบบล็อกของการแจงนับเป็นผลกระทบที่เกิดขึ้นตามธรรมชาติ
bbum

สิ่งนี้ดูเหมือนจะเร็วกว่ามาตรฐานสำหรับ ... ในโครงสร้าง: oneofthesedaysblog.com/block-vs-for-in-objective-c-enumeration oneofthesedaysblog.com/block-vk
8k1111

1
@ lkraider ฉันแสดงความคิดเห็นในโพสต์นั้นซึ่งจริง ๆ แล้วเปรียบเทียบการนับบล็อกตามกับเก่าสำหรับวนไม่ใช่สำหรับ ... ในการสร้าง
Quinn Taylor

มีไว้*stopเพื่ออะไร? คุณใช้มันอย่างไร? การอ้างอิงใด ๆ
borisdiakur

13

หากคุณจำเป็นต้องกลายพันธุ์พจนานุกรมในขณะที่การแจกแจง:

for (NSString* key in xyz.allKeys) {
    [xyz setValue:[NSNumber numberWithBool:YES] forKey:key];
}

เหตุผลคือallKeysส่งคืนสำเนาของคีย์ ดังนั้นจึงปลอดภัยในการกลายพันธุ์พจนานุกรม
Honghao Zhang

5

วิธีที่ง่ายที่สุดในการระบุพจนานุกรมคือ

for (NSString *key in tDictionary.keyEnumerator) 
{
    //do something here;
}

ที่tDictionaryเป็นNSDictionaryหรือNSMutableDictionaryคุณต้องการที่จะย้ำ


4

ผมขอแนะนำให้คุณอ่านการแจงนับ: Traversing องค์ประกอบของการเก็บส่วนหนึ่งของคอลเลกชัน Programming คู่มือสำหรับโกโก้ มีรหัสตัวอย่างสำหรับความต้องการของคุณ


สิ่งเหล่านี้คือลิงค์ที่ดีแม้ว่าโค้ด @zneak ที่โพสต์นั้นง่ายกว่าและเร็วกว่ามากหากคุณสามารถสร้างขึ้นสำหรับ 10.5+ หรือ iPhone
Quinn Taylor

2

มีการเพิ่มการแจงนับอย่างรวดเร็วใน 10.5 และใน iPhone OS และมันเร็วกว่าอย่างมากไม่ใช่แค่น้ำตาลเชิงประโยค หากคุณต้องกำหนดเป้าหมายรันไทม์รุ่นเก่า (เช่น 10.4 และย้อนกลับ) คุณจะต้องใช้วิธีการแบบเก่าของการแจกแจง:

NSDictionary *myDict = ... some keys and values ...
NSEnumerator *keyEnum = [myDict keyEnumerator];
id key;

while ((key = [keyEnum nextObject]))
{
    id value = [myDict objectForKey:key];
    ... do work with "value" ...
}

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


1

คุณสามารถใช้-[NSDictionary allKeys]เพื่อเข้าถึงปุ่มทั้งหมดและวนผ่านมันได้


2
จริง แต่วิธีนี้จะสร้างอาร์เรย์ autoreleded พิเศษซึ่งอาจสิ้นเปลืองโดยเฉพาะพจนานุกรมที่มีกุญแจจำนวนมาก
Quinn Taylor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.