Kapan lebih baik menggunakan NSSet daripada NSArray?

112

Saya telah menggunakan NSSets berkali-kali di aplikasi saya, tetapi saya tidak pernah membuatnya sendiri.

Kapan lebih baik menggunakan an NSSetsebagai lawan NSArraydan mengapa?

geminiCoder
sumber

Jawaban:

173

Jika urutan item dalam koleksi tidak penting, set menawarkan kinerja yang lebih baik untuk menemukan item dalam koleksi.

Alasannya adalah bahwa satu set menggunakan nilai hash untuk menemukan item (seperti kamus) sementara array harus mengulangi seluruh isinya untuk menemukan objek tertentu.

Ole Begemann
sumber
9
log (1) vs log (n)
rohan-patel
25
@ rohan-patel Benar adalah O (1) vs O (n)
Mansurov Ruslan
1
Jika dipesan: O (1) vs O (logn) karena pencarian biner dapat diterapkan. Jika tidak diurutkan, maka O (1) vs O (n)
baskInEminence
180

Gambar dari Dokumentasi Apple menggambarkannya dengan sangat baik:

Koleksi Objective-C

Arrayadalah sebuah memerintahkan (agar dipertahankan ketika Anda menambahkan) urutan elemen

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

Setadalah daftar elemen yang berbeda (tidak ada duplikat) dan tidak berurutan

[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]
James Webster
sumber
2
Dalam contoh Anda, Anda menambahkan primitif ke array dan set. Keduanya tidak mungkin karena hanya berisi objek.
FreeAsInBeer
10
Terima kasih sudah mengedit @Zaheer, tapi sebenarnya tidak valid. Saya tidak menambahkan primitif. Saya menambahkan literal.
James Webster
Penjelasan bagus :) +1 :)
Karun
1
Suka penjelasan Anda! +1 untuk itu
pemberontakan
66

Jawaban terbaik untuk ini adalah dokumentasi Apple sendiri .

masukkan deskripsi gambar di sini

Perbedaan utamanya NSArrayadalah untuk koleksi yang dipesan dan NSSetuntuk koleksi yang tidak diurutkan .

Ada beberapa artikel di luar sana yang membahas tentang perbedaan kecepatan antara keduanya, seperti ini . Jika Anda mengulang melalui koleksi yang tidak diurutkan, NSSetitu bagus. Namun, dalam banyak kasus, Anda perlu melakukan hal-hal yang hanya NSArraydapat dilakukan, jadi Anda mengorbankan kecepatan untuk kemampuan tersebut.

NSSet

  • Terutama mengakses item sebagai perbandingan
  • Tidak dipesan
  • Tidak mengizinkan duplikat

NSArray

  • Dapat mengakses item dengan indeks
  • Dipesan
  • Memungkinkan duplikat

Hanya itu yang benar-benar ada untuk itu! Beri tahu saya jika itu membantu.

woz
sumber
Anda tidak harus selalu berkorban NSSetdemi pengindeksan. Biasanya menggunakan dua struktur data yang berbeda untuk data yang sama. Atau Anda membangun dan mengindeks pada array tersebut :) Tapi lebih baik menggunakan DB yang sudah diimplementasikan.
Sulthan
"Bangun indeks pada larik itu". Anda tidak dapat membuat indeks di NSSet. Ada banyak teknik berbeda yang dapat Anda gunakan. Dan jika Anda perlu berkorban dalam KEDUA memori dan kekuatan pemrosesan, maka Anda salah melakukannya.
Sulthan
Karena pertanyaannya tentang NSSetdan NSArray, jawaban saya akurat dan lengkap. Ya, Anda dapat membangun struktur data lain, tetapi saya hanya membandingkan keduanya.
woz
Saya melakukan upvote tetapi jawaban Anda salah ketika Anda berbicara tentang pengorbanan. Jika Anda memerlukan beberapa fungsionalitas dari NSArraydan beberapa fungsi dari NSSet, jawaban yang benar bukanlah "menggunakan NSArraydan mengorbankan kinerja". Jawabannya adalah menggabungkan keduanya atau menggunakan struktur data yang berbeda.
Sulthan
Saya akan mengatakan perbedaan utama diatur adalah untuk objek unik di mana array dapat memiliki duplikat. Aspek keteraturan adalah nomor dua dari fakta itu.
malhal
12

NSOrderedSet tersedia di iOS 5+ sehingga perbedaan utamanya adalah apakah Anda ingin objek duplikat dalam struktur data.

Jason
sumber
9

NSArray :

  1. Pengumpulan data yang dipesan
  2. Memungkinkan duplikat
  3. Ini adalah objek tipe koleksi

NSSet :

  1. Pengumpulan data tidak berurutan
  2. Tidak mengizinkan duplikat
  3. Ini juga merupakan objek tipe koleksi
iOS Lifee
sumber
7

Sebuah array digunakan untuk mengakses item dengan indeksnya. Item apa pun dapat dimasukkan ke dalam array beberapa kali. Array menjaga urutan elemennya.

Satu set pada dasarnya digunakan hanya untuk memeriksa apakah item tersebut ada dalam koleksi atau tidak. Item tidak memiliki konsep urutan atau pengindeksan. Anda tidak dapat memiliki item dalam satu set dua kali.

Jika sebuah array ingin memeriksa apakah mengandung sebuah elemen, ia harus memeriksa semua itemnya. Set dirancang untuk menggunakan algoritme yang lebih cepat.

Anda bisa membayangkan satu set seperti kamus tanpa nilai.

Perhatikan bahwa array dan set bukanlah satu-satunya struktur data. Ada yang lainnya, misal Queue, Stack, Heap, Fibonacci's Heap. Saya akan merekomendasikan membaca buku tentang algoritma dan struktur data.

Lihat wikipedia untuk informasi lebih lanjut.

Sulthan
sumber
Sebenarnya, sebuah array hanya perlu diperiksa sampai item tersebut ditemukan. Jika item IS dalam larik, sangat jarang setiap item perlu diperiksa.
FreeAsInBeer
Ya, seperti yang Anda katakan "jika item IS dalam larik". Jika Anda mengharapkan ini, Anda tidak perlu memeriksa apakah itu ada atau tidak. Kompleksitas containsoperasinya O(n). Jumlah perbandingan jika tidak ada dalam array n. Jumlah rata-rata perbandingan saat objek berada dalam larik adalah n/2. Bahkan jika objeknya ditemukan, kinerjanya buruk.
Sulthan
Performa hanya akan buruk dengan array yang besar. Jika Anda tahu bahwa array bisa menjadi sangat besar, maka ada cara untuk meningkatkan kinerja array, seperti menggunakan array.
FreeAsInBeer
Jika operasi kesetaraan mahal, Anda akan melihat perbedaannya bahkan pada array dengan 3 item. Dan perilaku yang sama seperti array besar dapat terjadi jika Anda sering mengulang operasi (misalnya, gunakan operasi dalam siklus 'untuk'). Pernahkah Anda mendengar tentang kompleksitas yang diamortisasi? Kompleksitasnya masih linier dan kinerjanya buruk dibandingkan dengan satu set (biasanya dengan kompleksitas konstan).
Sulthan
Jelas akan ada perbedaan, saya hanya menyatakan bahwa notasi o besar adalah eksponensial; dengan larik kecil, perbedaannya akan sangat kecil. Juga, NSArrays memiliki keunggulan kecepatan lainnya dibandingkan NSSets. Seperti biasa, ini adalah pengorbanan.
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);

larik

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

set

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

abc221
sumber
4

Perbedaan utama telah diberikan dalam jawaban lain.

Saya hanya ingin mencatat bahwa karena cara set dan kamus diimplementasikan (yaitu menggunakan hash), seseorang harus berhati-hati untuk tidak menggunakan objek yang bisa berubah untuk kunci.

Jika kunci dimutasi maka hash (mungkin) juga akan berubah, menunjuk ke indeks / keranjang yang berbeda dalam tabel hash. Nilai asli tidak akan dihapus dan akan benar-benar diperhitungkan saat menghitung atau menanyakan struktur untuk ukuran / hitungannya.

Ini dapat menyebabkan beberapa bug sangat sulit ditemukan.

joakim
sumber
3

Di sini Anda dapat menemukan perbandingan yang cukup menyeluruh dari struktur data NSArraydan NSSet.

Kesimpulan singkat:

Ya, NSArray lebih cepat daripada NSSet karena hanya menahan dan mengulang. Lebih cepat 50% untuk membangun dan 500% lebih cepat untuk iterasi. Pelajaran: jika Anda hanya perlu mengulang konten, jangan gunakan NSSet.

Tentu saja, jika Anda perlu menguji inklusi, bekerja keras untuk menghindari NSArray. Bahkan jika Anda membutuhkan pengujian iterasi dan inklusi, Anda mungkin masih harus memilih NSSet. Jika Anda perlu menjaga agar koleksi Anda tetap teratur dan juga menguji penyertaan, Anda harus mempertimbangkan untuk menyimpan dua koleksi (NSArray dan NSSet), masing-masing berisi objek yang sama.

NSDictionary lebih lambat untuk dibuat daripada NSMapTable - karena perlu menyalin data kunci. Itu membuat ini dengan menjadi lebih cepat untuk mencari. Tentu saja, keduanya memiliki kemampuan yang berbeda sehingga seringkali penentuan ini harus dilakukan pada faktor-faktor lain.

Che
sumber
Meskipun ini secara teoritis dapat menjawab pertanyaan, akan lebih baik jika menyertakan bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
Tunaki
2

Anda biasanya akan menggunakan Set ketika kecepatan akses adalah yang terpenting dan urutan tidak penting , atau ditentukan dengan cara lain (melalui predikat atau deskriptor sortir). Data Inti misalnya menggunakan set ketika objek yang dikelola diakses melalui hubungan ke banyak

iDevAmit
sumber
1

Hanya untuk menambahkan sedikit saja saya menggunakan set kadang-kadang hanya untuk menghapus duplikat dari array seperti: -

NSMutableSet *set=[[NSMutableSet alloc]initWithArray:duplicateValueArray]; // will remove all the duplicate values
tryKuldeepTanwar
sumber