เมื่อใดที่ควรใช้ NSSet กับ NSArray


คำตอบ:


173

เมื่อลำดับของรายการในคอลเลกชันไม่สำคัญชุดจะมีประสิทธิภาพที่ดีกว่าในการค้นหารายการในคอลเลกชัน

เหตุผลก็คือชุดใช้ค่าแฮชเพื่อค้นหารายการ (เช่นพจนานุกรม) ในขณะที่อาร์เรย์ต้องวนซ้ำเนื้อหาทั้งหมดเพื่อค้นหาวัตถุเฉพาะ


9
log (1) vs log (n)
rohan-patel

25
@ rohan-patel Correct is O (1) vs O (n)
Mansurov Ruslan

1
ถ้าเรียงลำดับ: O (1) vs O (logn) เนื่องจากสามารถใช้การค้นหาไบนารีได้ ถ้าไม่เรียงลำดับ O (1) vs O (n)
baskInEminence

180

ภาพจากเอกสารของ Appleอธิบายได้เป็นอย่างดี:

คอลเลกชัน Objective-C

Arrayเป็นลำดับ (ลำดับจะคงอยู่เมื่อคุณเพิ่ม) ลำดับขององค์ประกอบ

[array addObject:@1];
[array addObject:@2];
[array addObject:@3];
[array addObject:@4];
[array addObject:@6];
[array addObject:@4];
[array addObject:@1];
[array addObject:@2];

[1, 2, 3, 4, 6, 4, 1, 2]

Setเป็นรายการองค์ประกอบที่แตกต่างกัน (ไม่ซ้ำกัน) โดยไม่เรียงลำดับ

[set addObject:@1];
[set addObject:@2];
[set addObject:@3];
[set addObject:@4];
[set addObject:@6];
[set addObject:@4];
[set addObject:@1];
[set addObject:@2];

[1, 2, 6, 4, 3]

2
ในตัวอย่างของคุณคุณกำลังเพิ่ม primitives ให้กับอาร์เรย์และชุด เป็นไปไม่ได้เพราะสามารถมีได้เฉพาะวัตถุ
FreeAsInBeer

10
ขอบคุณสำหรับการแก้ไขของคุณ @Zaheer แต่จริงๆแล้วมันไม่ถูกต้อง ฉันไม่ได้เพิ่มแบบดั้งเดิม ฉันกำลังเพิ่มตัวอักษร
James Webster

คำอธิบายที่ดี :) +1 :)
Karun

1
รักคำอธิบายของคุณ! +1 สำหรับสิ่งนั้น
การกบฏ

66

คำตอบที่ดีที่สุดคือการนี้เป็นเอกสารของตัวเองแอปเปิ้ล

ใส่คำอธิบายภาพที่นี่

ความแตกต่างที่สำคัญNSArrayคือสำหรับคอลเลกชันที่สั่งซื้อและNSSetสำหรับคอลเลกชันที่ไม่มีการเรียงลำดับ

มีหลายบทความออกมีที่พูดคุยเกี่ยวกับความแตกต่างในความเร็วระหว่างสองเหมือนเป็นคนนี้ หากคุณทำซ้ำผ่านคอลเลกชันที่ไม่มีการเรียงลำดับNSSetจะดีมาก อย่างไรก็ตามในหลาย ๆ กรณีคุณต้องทำสิ่งที่ทำได้เพียงอย่างเดียวNSArrayดังนั้นคุณจึงยอมสละความเร็วเพื่อความสามารถเหล่านั้น

NSSet

  • เข้าถึงรายการโดยการเปรียบเทียบเป็นหลัก
  • เรียงลำดับ
  • ไม่อนุญาตให้มีการทำซ้ำ

NSArray

  • สามารถเข้าถึงรายการโดยดัชนี
  • สั่งซื้อ
  • อนุญาตให้ทำซ้ำ

นั่นคือทั้งหมดที่มีจริงๆ! แจ้งให้เราทราบหากช่วยได้


คุณไม่จำเป็นต้องเสียสละNSSetเพื่อการจัดทำดัชนีเสมอไป เป็นเรื่องปกติที่จะใช้โครงสร้างข้อมูลสองแบบที่แตกต่างกันสำหรับข้อมูลเดียวกัน หรือคุณสร้างและทำดัชนีในอาร์เรย์นั้น :) แต่จะดีกว่าถ้าใช้ฐานข้อมูลที่มีการนำไปใช้งาน
Sulthan

"สร้างดัชนีในอาร์เรย์นั้น" คุณไม่สามารถสร้างดัชนีบน NSSet ได้ มีเทคนิคต่างๆมากมายที่คุณสามารถใช้ได้ และหากคุณจำเป็นต้องเสียสละทั้งหน่วยความจำและพลังการประมวลผลแสดงว่าคุณทำผิด
Sulthan

เนื่องจากคำถามเกี่ยวกับNSSetและNSArrayคำตอบของฉันจึงถูกต้องและสมบูรณ์ ใช่คุณสามารถสร้างโครงสร้างข้อมูลอื่น ๆ ได้ แต่ฉันแค่เปรียบเทียบสองสิ่งนี้
woz

ฉันโหวตให้แล้ว แต่คำตอบของคุณไม่ถูกต้องเมื่อคุณพูดเกี่ยวกับการเสียสละ หากคุณต้องการฟังก์ชั่นบางอย่างจากNSArrayและ functioanlity จากNSSetคำตอบที่ถูกต้องคือไม่ได้ "การใช้งานNSArrayและการเสียสละประสิทธิภาพ" คำตอบคือรวมทั้งสองอย่างหรือใช้โครงสร้างข้อมูลที่แตกต่างกัน
Sulthan

ฉันจะบอกว่าความแตกต่างหลักคือการตั้งค่าสำหรับอ็อบเจ็กต์ที่ไม่ซ้ำกันซึ่งอาร์เรย์สามารถมีรายการซ้ำกันได้ ด้านการสั่งซื้อเป็นรองจากข้อเท็จจริงนั้น
malhal

12

NSOrderSet พร้อมใช้งานใน iOS 5+ ดังนั้นความแตกต่างที่สำคัญจะกลายเป็นว่าคุณต้องการให้วัตถุซ้ำกันในโครงสร้างข้อมูลหรือไม่


9

NSArray :

  1. สั่งรวบรวมข้อมูล
  2. อนุญาตให้ทำซ้ำ
  3. เป็นวัตถุประเภทคอลเลกชัน

NSSet :

  1. การรวบรวมข้อมูลที่ไม่เรียงลำดับ
  2. ไม่อนุญาตให้มีการทำซ้ำ
  3. นอกจากนี้ยังเป็นวัตถุประเภทคอลเลกชัน

7

อาร์เรย์ใช้เพื่อเข้าถึงรายการโดยดัชนีของพวกเขา รายการใด ๆ สามารถแทรกลงในอาร์เรย์ได้หลายครั้ง อาร์เรย์เป็นส่วนหนึ่งของลำดับขององค์ประกอบ

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

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

คุณสามารถจินตนาการถึงชุดเช่นพจนานุกรมที่ไม่มีค่า

โปรดทราบว่าอาร์เรย์และชุดไม่ใช่โครงสร้างข้อมูลเพียงอย่างเดียว ยังมีอีกเช่น Queue, Stack, Heap, Fibonacci's Heap ฉันอยากจะแนะนำให้อ่านหนังสือเกี่ยวกับอัลกอริทึมและโครงสร้างข้อมูล

ดูวิกิพีเดียสำหรับข้อมูลเพิ่มเติม


ที่จริงแล้วอาร์เรย์จะต้องได้รับการตรวจสอบจนถึงจุดที่พบรายการเท่านั้น หากรายการ IS ในอาร์เรย์แทบจะไม่จำเป็นต้องตรวจสอบทุกรายการ
FreeAsInBeer

ใช่ตามที่คุณพูดว่า "if the item IS in the array" หากคุณคาดหวังสิ่งนี้คุณไม่จำเป็นต้องตรวจสอบว่ามีหรือไม่ ความซับซ้อนของการดำเนินงานคือcontains จำนวนของการเปรียบเทียบเมื่อไม่ได้อยู่ในอาร์เรย์O(n) จำนวนเฉลี่ยของการเปรียบเทียบเมื่อวัตถุอยู่ในอาร์เรย์คือn n/2แม้ว่าจะพบวัตถุ แต่ประสิทธิภาพก็แย่มาก
Sulthan

ประสิทธิภาพจะแย่กับอาร์เรย์ขนาดใหญ่เท่านั้น หากคุณรู้ว่าอาร์เรย์อาจมีขนาดค่อนข้างใหญ่มีหลายวิธีที่คุณสามารถปรับปรุงประสิทธิภาพของอาร์เรย์ได้เช่นการใช้อาร์เรย์อาร์เรย์
FreeAsInBeer

หากการดำเนินการความเท่าเทียมกันมีราคาแพงคุณจะเห็นความแตกต่างแม้ในอาร์เรย์ที่มี 3 รายการ และพฤติกรรมเดียวกันกับอาร์เรย์ขนาดใหญ่สามารถเกิดขึ้นได้เมื่อคุณทำซ้ำการดำเนินการเป็นจำนวนมาก (เช่นใช้การดำเนินการในวงจร 'สำหรับ') คุณเคยได้ยินเกี่ยวกับความซับซ้อนในการตัดจำหน่ายหรือไม่? ความซับซ้อนยังคงเป็นเส้นตรงและประสิทธิภาพนั้นแย่มากเมื่อเทียบกับชุดหนึ่ง (โดยปกติจะมีความซับซ้อนคงที่)
Sulthan

เห็นได้ชัดว่าจะมีความแตกต่างฉันแค่บอกว่าสัญกรณ์ o ใหญ่เป็นเลขชี้กำลัง ด้วยอาร์เรย์ขนาดเล็กความแตกต่างจะเป็นเพียงเล็กน้อย นอกจากนี้NSArrays ยังมีข้อได้เปรียบด้านความเร็วอื่น ๆ มากกว่าNSSets เช่นเคยมันเป็นการแลกเปลี่ยน
FreeAsInBeer

5
NSArray *Arr;
NSSet *Nset;

Arr=[NSArray arrayWithObjects:@"1",@"2",@"3",@"4",@"2",@"1", nil];
Nset=[NSSet setWithObjects:@"1",@"2",@"3",@"3",@"5",@"5", nil];

NSLog(@"%@",Arr);
NSLog(@"%@",Nset);

อาร์เรย์

2015-12-04 11: 05: 40.935 [598: 15730] (1, 2, 3, 4, 2, 1)

ชุด

2015-12-04 11: 05: 43.362 [598: 15730] {(3, 1, 2, 5)}


4

ความแตกต่างหลักได้รับไปแล้วในคำตอบอื่น ๆ

ฉันแค่อยากจะทราบว่าเนื่องจากวิธีการใช้งานชุดและพจนานุกรม (เช่นการใช้แฮช) จึงควรระมัดระวังไม่ให้ใช้วัตถุที่ไม่แน่นอนสำหรับคีย์

หากคีย์ถูกกลายพันธุ์แฮชก็จะ (อาจ) เปลี่ยนไปด้วยโดยชี้ไปที่ดัชนี / ที่เก็บข้อมูลอื่นในตารางแฮช ค่าดั้งเดิมจะไม่ถูกลบและจะนำมาพิจารณาเมื่อแจกแจงหรือถามโครงสร้างสำหรับขนาด / จำนวน

ซึ่งอาจนำไปสู่การหาจุดบกพร่องได้ยาก


3

ที่นี่คุณสามารถค้นหาเปรียบเทียบอย่างละเอียดสวยของNSArrayและNSSetdatastructures

ข้อสรุปสั้น ๆ :

ใช่ NSArray เร็วกว่า NSSet เพียงแค่ถือและทำซ้ำ เร็วขึ้นเพียง 50% สำหรับการสร้างและการทำซ้ำเร็วขึ้นมากถึง 500% บทเรียน: หากคุณจำเป็นต้องทำซ้ำเนื้อหาอย่าใช้ NSSet

แน่นอนว่าหากคุณต้องการทดสอบการรวมเข้าด้วยกันให้พยายามหลีกเลี่ยง NSArray แม้ว่าคุณจะต้องการทั้งการทดสอบซ้ำและการทดสอบรวมคุณก็ยังควรเลือก NSSet หากคุณต้องการให้คอลเลคชันของคุณเป็นระเบียบและทดสอบการรวมด้วยคุณควรพิจารณาเก็บสองคอลเลคชัน (NSArray และ NSSet) โดยแต่ละคอลเลคชันมีวัตถุเดียวกัน

NSDictionary สร้างช้ากว่า NSMapTable - เนื่องจากต้องคัดลอกข้อมูลสำคัญ ทำให้ขึ้นโดยการค้นหาได้เร็วขึ้น แน่นอนว่าทั้งสองมีความสามารถที่แตกต่างกันโดยส่วนใหญ่แล้วการตัดสินใจนี้ควรพิจารณาจากปัจจัยอื่น ๆ


ในขณะนี้อาจตอบคำถามในทางทฤษฎีได้ แต่ควรรวมส่วนสำคัญของคำตอบไว้ที่นี่และระบุลิงก์สำหรับการอ้างอิง
Tunaki

2

โดยทั่วไปคุณจะใช้Set เมื่อความเร็วในการเข้าถึงเป็นสิ่งสำคัญและลำดับไม่สำคัญหรือถูกกำหนดโดยวิธีอื่น (ผ่านตัวอธิบายเพรดิเคตหรือการเรียงลำดับ) ข้อมูลหลักเช่นใช้ชุดเมื่ออ็อบเจ็กต์ที่มีการจัดการถูกเข้าถึงผ่านความสัมพันธ์ต่อกลุ่ม


1

เพียงเพื่อเพิ่มเล็กน้อยฉันใช้ set บางครั้งเพื่อลบรายการที่ซ้ำกันออกจากอาร์เรย์เช่น: -

NSMutableSet *set=[[NSMutableSet alloc]initWithArray:duplicateValueArray]; // will remove all the duplicate values
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.