Cara terbaik untuk menghapus nilai duplikat ( NSString
) dari NSMutableArray
di Objective-C?
Apakah ini cara termudah dan tepat untuk melakukannya?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
ios
objective-c
nsmutablearray
Teo Choong Ping
sumber
sumber
Jawaban:
NSSet
Pendekatan Anda adalah yang terbaik jika Anda tidak khawatir tentang urutan objek, tetapi sekali lagi, jika Anda tidak khawatir tentang urutannya, lalu mengapa Anda tidak menyimpannya diNSSet
awal?Saya menulis jawaban di bawah ini pada tahun 2009; pada tahun 2011, Apple ditambahkan
NSOrderedSet
ke iOS 5 dan Mac OS X 10.7. Apa yang tadinya merupakan algoritma sekarang adalah dua baris kode:Jika Anda khawatir tentang pesanan dan Anda menjalankan iOS 4 atau lebih lama, lewati salinan array:
sumber
[NSOrderedSet orderedSetWithArray:array];
Anda kemudian dapat kembali array melaluiarray = [orderedSet allObjects];
atau hanya menggunakanNSOrderedSet
s bukanNSArray
di tempat pertama.[orderedSet allObjects]
dengan[orderedSet array]
!NSArray
dan harus membuat tempNSMutableArray
. Dalam contoh Anda, Anda bekerja sebaliknyaNSSet
Adakah yang tahu pandangan terbaik untuk menghapus duplikat apakah metode ini (menggunakan ) atau tautan @Simon Whitaker mencegah sebelum menambahkan nilai duplikat yang merupakan cara efisien?Saya tahu ini adalah pertanyaan lama, tetapi ada cara yang lebih elegan untuk menghapus duplikat di
NSArray
jika Anda tidak peduli dengan pesanan .Jika kita menggunakan Object Operator dari Key Value Coding kita bisa melakukan ini:
Sebagai AnthoPak juga mencatat adalah mungkin untuk menghapus duplikat berdasarkan properti. Contohnya adalah:
@distinctUnionOfObjects.name
sumber
@distinctUnionOfObjects.property
untuk menghapus duplikat berdasarkan properti dari array objek kustom. Misalnya@distinctUnionOfObjects.name
Ya, menggunakan NSSet adalah pendekatan yang masuk akal.
Untuk menambah jawaban Jim Puls, berikut adalah pendekatan alternatif untuk menghapus duplikat sambil mempertahankan pesanan:
Ini pada dasarnya pendekatan yang sama dengan Jim tetapi menyalin item unik ke array yang bisa berubah baru daripada menghapus duplikat dari aslinya. Ini membuatnya sedikit lebih efisien dalam hal array besar dengan banyak duplikat (tidak perlu membuat salinan seluruh array), dan menurut saya sedikit lebih mudah dibaca.
Perhatikan bahwa dalam kedua kasus, memeriksa untuk melihat apakah item sudah termasuk dalam array target (menggunakan
containsObject:
dalam contoh saya, atauindexOfObject:inRange:
dalam Jim) tidak skala dengan baik untuk array besar. Pemeriksaan tersebut berjalan dalam waktu O (N), yang berarti bahwa jika Anda menggandakan ukuran array asli maka setiap pemeriksaan akan memakan waktu dua kali lebih lama untuk dijalankan. Karena Anda melakukan pemeriksaan untuk setiap objek dalam array, Anda juga akan menjalankan lebih banyak dari pemeriksaan yang lebih mahal itu. Algoritma keseluruhan (baik milik saya maupun Jim) berjalan dalam waktu O (N 2 ), yang menjadi cepat mahal seiring dengan tumbuhnya array asli.Untuk menurunkannya ke waktu O (N), Anda bisa menggunakan a
NSMutableSet
untuk menyimpan catatan item yang sudah ditambahkan ke array baru, karena pencarian NSSet adalah O (1) daripada O (N). Dengan kata lain, memeriksa untuk melihat apakah suatu elemen adalah anggota NSSet membutuhkan waktu yang sama terlepas dari berapa banyak elemen dalam set.Kode yang menggunakan pendekatan ini akan terlihat seperti ini:
Ini tampaknya masih sedikit boros; kami masih membuat array baru ketika pertanyaan menjelaskan bahwa array asli bisa berubah, jadi kita harus dapat menghapusnya di tempat dan menghemat memori. Sesuatu seperti ini:
UPDATE : Yuri Niyazov menunjukkan bahwa jawaban terakhir saya benar-benar berjalan di O (N 2 ) karena
removeObjectAtIndex:
mungkin berjalan dalam waktu O (N).(Dia mengatakan "mungkin" karena kita tidak tahu pasti bagaimana itu diterapkan; tetapi satu kemungkinan implementasi adalah bahwa setelah menghapus objek pada indeks X metode kemudian loop melalui setiap elemen dari indeks X + 1 ke objek terakhir dalam array , memindahkan mereka ke indeks sebelumnya. Jika itu masalahnya maka itu memang kinerja O (N).)
Jadi, apa yang harus dilakukan? Itu tergantung situasi. Jika Anda memiliki array besar dan Anda hanya mengharapkan sejumlah kecil duplikat maka de-duplikasi di tempat akan bekerja dengan baik dan menghemat Anda harus membangun array duplikat. Jika Anda memiliki array di mana Anda mengharapkan banyak duplikat kemudian membangun array terpisah, de-duped mungkin merupakan pendekatan terbaik. Yang dibawa pulang di sini adalah bahwa notasi-O besar hanya menggambarkan karakteristik suatu algoritma, itu tidak akan memberi tahu Anda secara definitif mana yang terbaik untuk keadaan apa pun.
sumber
Jika Anda menargetkan iOS 5+ (yang mencakup seluruh dunia iOS), gunakan yang terbaik
NSOrderedSet
. Ini menghapus duplikat dan mempertahankan urutanNSArray
.Kerjakan saja
Anda sekarang dapat mengubahnya kembali ke NSArray unik
Atau cukup gunakan orderedetet karena memiliki metode yang sama seperti NSArray
objectAtIndex:
,firstObject
dan sebagainya.Pemeriksaan keanggotaan dengan
contains
bahkan lebih cepatNSOrderedSet
daripada padaNSArray
Untuk checkout lebih lanjut, Referensi NSOrderedSet
sumber
Tersedia dalam OS X v10.7 dan yang lebih baru.
Jika Anda khawatir tentang pesanan, cara yang benar untuk dilakukan
Berikut adalah kode untuk menghapus nilai duplikat dari NSArray dalam Pesanan.
sumber
butuh pesanan
atau tidak perlu dipesan
sumber
Di sini saya menghapus nilai nama duplikat dari mainArray dan menyimpan hasil di NSMutableArray (listOfUsers)
sumber
Perhatikan bahwa jika Anda memiliki array yang diurutkan, Anda tidak perlu memeriksa setiap item dalam array, hanya item terakhir. Ini harus jauh lebih cepat daripada memeriksa semua item.
Sepertinya
NSOrderedSet
jawaban yang juga disarankan memerlukan kode jauh lebih sedikit, tetapi jika Anda tidak dapat menggunakanNSOrderedSet
karena suatu alasan, dan Anda memiliki array yang diurutkan, saya percaya solusi saya akan menjadi yang tercepat. Saya tidak yakin bagaimana membandingkannya dengan kecepatanNSOrderedSet
solusi. Perhatikan juga bahwa kode saya sedang diperiksaisEqualToString:
, sehingga seri huruf yang sama tidak akan muncul lebih dari satu kalinewArray
. Saya tidak yakin apakahNSOrderedSet
solusi akan menghapus duplikat berdasarkan nilai atau berdasarkan lokasi memori.Contoh saya anggap
sortedSourceArray
berisi hanyaNSString
s, hanyaNSMutableString
s, atau campuran keduanya. JikasortedSourceArray
sebaliknya hanya berisiNSNumber
s atau hanyaNSDate
s, Anda dapat menggantidengan
dan itu harus bekerja dengan sempurna. Jika
sortedSourceArray
berisi campuranNSString
s,NSNumber
s, dan / atauNSDate
s, itu mungkin akan macet.sumber
Ada Operator Objek KVC yang menawarkan solusi yang lebih elegan.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
Ini adalah kategori NSArray .sumber
Satu lagi cara sederhana yang dapat Anda coba yang tidak akan menambah Nilai rangkap sebelum menambahkan objek dalam array: -
// Asumsikan mutableArray dialokasikan dan diinisialisasi dan berisi beberapa nilai
sumber
Hapus nilai duplikat dari NSMutableArray di Objective-C
sumber
Berikut adalah kode untuk menghapus nilai duplikat dari NSMutable Array. .itu akan bekerja untuk Anda. myArray adalah Array Mutable Anda yang ingin Anda hapus nilai duplikat ..
sumber
Menggunakan
Orderedset
akan melakukan trik. Ini akan menjaga agar duplikat yang dihapus dari array dan mempertahankan urutan yang biasanya tidak dilakukansumber
cukup gunakan kode sederhana ini:
karena nsset tidak mengizinkan nilai duplikat dan semua objek mengembalikan array
sumber
NSOrderedSet
insteed ofNSSet
.