NSArray yerine NSSet kullanmak ne zaman daha iyidir?


Yanıtlar:


173

Koleksiyondaki öğelerin sırası önemli olmadığında setler, koleksiyondaki öğeleri bulmak için daha iyi performans sunar.

Bunun nedeni, bir dizinin belirli bir nesneyi bulmak için tüm içeriğini yinelemek zorunda kalırken (bir sözlük gibi) öğeleri bulmak için karma değerleri kullanmasıdır.


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

25
@ rohan-patel Doğru olan O (1) - O (n)
Mansurov Ruslan

1
Sıralıysa: O (1) - O (logn) çünkü ikili arama uygulanabilir. Sırasız ise, O (1) - O (n)
baskInEminence

180

Apple'ın Belgelerindeki görsel bunu çok iyi açıklıyor:

Objective-C Koleksiyonları

ArrayBir olan sıralı elemanları dizisi (ekleme sırasında sipariş korunur)

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

Seta, tat (hiçbir çiftleri), düzensiz elemanların listesi

[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
Örneğinizde, bir dizi ve bir kümeye temel öğeler ekliyorsunuz. Bunların hiçbiri mümkün değildir çünkü bunlar yalnızca nesneleri içerebilir.
FreeAsInBeer

10
@ Zaheer düzenlemeniz için teşekkürler, ancak aslında geçersizdi. İlkelleri eklemiyordum. Değişmez değerler ekliyordum.
James Webster

Harika açıklama :) +1 :)
Karun

1
Açıklamanıza bayıldım! Bunun için +1
isyan

66

Buna en iyi cevap, Apple'ın kendi belgeleridir .

görüntü açıklamasını buraya girin

Temel fark, NSArraysıralı bir koleksiyon NSSetiçin ve sırasız bir koleksiyon içindir.

Orada birkaç makale gibi ikisi arasındaki hız farkı, bahsedip duran vardır bu bir . Sırasız bir koleksiyonla yineleme yapıyorsanız NSSet, harika. Bununla birlikte, çoğu durumda, yalnızca bir NSArraykişinin yapabileceği şeyleri yapmanız gerekir , bu nedenle bu yetenekler için hızınızı feda edersiniz.

NSSet

  • Öncelikle öğelere karşılaştırma yoluyla erişin
  • sırasız
  • Yinelemelere izin vermiyor

NSArray

  • Öğelere dizine göre erişebilir
  • düzenli
  • Yinelemelere izin verir

Gerçekten hepsi bu kadar! Yardımcı olacaksa bana haber ver.


NSSetİndeksleme uğruna her zaman fedakarlık yapmanız gerekmez . Aynı veriler için iki farklı veri yapısı kullanmak yaygındır. Ya da o diziyi oluşturur ve indekslersiniz :) Ama o zaman her zaman uygulanmış bir DB kullanmak daha iyidir.
Sulthan

"Bu dizi üzerinde bir dizin oluşturun". NSSet üzerinde bir dizin oluşturamazsınız. Kullanabileceğiniz birçok farklı teknik var. Hem bellek hem de işlem gücünden fedakarlık yapmanız gerekiyorsa, yanlış yapıyorsunuz demektir.
Sulthan

Soru NSSetve ile ilgili olduğu için NSArraycevabım doğru ve eksiksiz. Evet, başka veri yapıları oluşturabilirsiniz, ancak ben sadece bu ikisini karşılaştırıyorum.
woz

Olumlu oy verdim ama fedakarlıklardan bahsederken cevabınız yanlış. Bazı işlevlere NSArrayve bazı işlevlere ihtiyacınız varsa NSSet, doğru yanıt " NSArrayperformansı kullanın ve feda edin" değildir. Cevap, ikisini birleştirmek veya farklı bir veri yapısı kullanmaktır.
Sulthan

Ana farkın, bir dizinin kopyaları olabileceği benzersiz nesneler için ayarlandığını söyleyebilirim. Düzen yönü bu gerçeğe göre ikincildir.
malhal

12

NSOrderedSet, iOS 5+ sürümünde mevcuttur, bu nedenle temel fark, veri yapısında yinelenen nesneler isteyip istemediğiniz olur.


9

NSArray :

  1. Sıralı veri toplama
  2. Yinelemelere izin verir
  3. Koleksiyon türü nesnesidir

NSSet :

  1. Sırasız veri toplama
  2. Yinelemelere izin vermiyor
  3. Aynı zamanda koleksiyon türü nesnesidir

7

Öğelere dizinlerine göre erişmek için bir dizi kullanılır. Herhangi bir öğe diziye birden çok kez eklenebilir. Diziler, öğelerinin sırasını korur.

Bir set, temelde yalnızca öğenin koleksiyonda olup olmadığını kontrol etmek için kullanılır. Öğelerin sıralama veya indeksleme kavramı yoktur. Bir sette iki kez öğe bulunduramazsınız.

Bir dizi bir eleman içerip içermediğini kontrol etmek isterse, tüm öğelerini kontrol etmelidir. Kümeler, daha hızlı algoritmalar kullanmak üzere tasarlanmıştır.

Değerleri olmayan bir sözlük gibi bir set hayal edebilirsiniz.

Dizi ve kümenin tek veri yapıları olmadığını unutmayın. Sıra, Yığın, Yığın, Fibonacci'nin Yığını gibi başka şeyler de vardır. Algoritmalar ve veri yapıları hakkında bir kitap okumanızı tavsiye ederim.

Daha fazla bilgi için wikipedia'ya bakın .


Aslında, bir dizinin yalnızca öğenin bulunduğu noktaya kadar kontrol edilmesi gerekir. Öğe dizide ise, çok nadiren her öğenin kontrol edilmesi gerekir.
FreeAsInBeer

Evet, dediğiniz gibi "öğe dizide ise". Bunu beklerseniz, orada olup olmadığını kontrol etmeniz gerekmez. Karmaşıklığı containsoperasyonu olduğunu O(n). Dizide bulunmadığında yapılan karşılaştırmaların sayısı n. Nesne dizide olduğunda ortalama karşılaştırma sayısı 'dır n/2. Nesne bulunsa bile, performans berbat.
Sulthan

Performans, yalnızca geniş bir diziyle kötü olur. Dizinin oldukça büyük olabileceğini biliyorsanız, bir dizi dizisi kullanmak gibi dizinin performansını artırmanın yolları vardır.
FreeAsInBeer

Eşitlik işlemi pahalıysa, farkı 3 öğeli dizilerde bile göreceksiniz. Ve büyük bir diziyle aynı davranış, işlemi çok tekrarladığınızda gerçekleşebilir (örneğin, işlemi 'for' döngüsünde kullanın). Amortize edilmiş karmaşıklık hakkında bir şeyler duydunuz mu? Karmaşıklık hala doğrusaldır ve performans bir sete kıyasla çok kötüdür (genellikle sabit karmaşıklıkla).
Sulthan

Açıkçası bir fark olacak, sadece büyük notasyonun üstel olduğunu söylüyorum; küçük dizilerde fark çok küçük olacaktır. Ayrıca, NSArrays'ye göre başka hız avantajları da vardır NSSet. Her zaman olduğu gibi, bu bir değiş tokuş.
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);

dizi

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

set

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


4

Ana farklılıklar zaten diğer cevaplarda verilmiştir.

Kümeler ve sözlüklerin uygulanma şekli nedeniyle (yani hash kullanımı), anahtarlar için değişken nesneler kullanılmamasına dikkat edilmesi gerektiğini belirtmek isterim.

Bir anahtar mutasyona uğratılırsa, karma (muhtemelen) de değişecek ve karma tablosunda farklı bir dizine / kova işaret edecektir. Orijinal değer silinmeyecek ve yapıyı numaralandırırken veya boyutu / sayısını sorarken aslında dikkate alınacaktır.

Bu, bazı hataların bulunmasının gerçekten zor olmasına yol açabilir.


3

İşte size bir güzel ayrıntılı karşılaştırmasını bulabilirsiniz NSArrayve NSSetveriyapılarıdır.

Kısa sonuçlar:

Evet, NSArray, yalnızca tutma ve yineleme açısından NSSet'ten daha hızlıdır. Oluşturma için% 50 kadar az ve yineleme için% 500 kadar daha hızlı. Ders: Yalnızca içeriği yinelemeniz gerekiyorsa, NSSet kullanmayın.

Elbette, dahil etme için test etmeniz gerekiyorsa, NSArray'den kaçınmak için çok çalışın. Hem yineleme hem de dahil etme testine ihtiyacınız olsa bile, muhtemelen yine de bir NSSet seçmelisiniz. Koleksiyonunuzu düzenli tutmanız ve ayrıca dahil edilmek için test etmeniz gerekiyorsa, her biri aynı nesneleri içeren iki koleksiyon (bir NSArray ve bir NSSet) tutmayı düşünmelisiniz.

NSDictionary, NSMapTable'dan daha yavaştır - çünkü anahtar verilerini kopyalamalıdır. Daha hızlı arama yaparak bunu telafi eder. Elbette ikisinin farklı yetenekleri var, bu yüzden çoğu zaman bu belirleme başka faktörler üzerinden yapılmalıdır.


Bu teorik olarak soruya cevap görülebilir fakat tercih edildiğini burada cevabın temel parçalarını kapsadığı ve başvuru için bağlantı sağlar.
Tunaki

2

Erişim hızı önemli olduğunda ve düzen önemli olmadığında veya başka yollarla belirlendiğinde (bir yüklem veya sıralama tanımlayıcısı aracılığıyla) tipik olarak bir Küme kullanırsınız . Örneğin Çekirdek Veriler, yönetilen nesnelere bir-çok ilişkisi aracılığıyla erişildiğinde kümeler kullanır


1

Sadece biraz eklemek için bazen sadece diziden kopyaları kaldırmak için kullanıyorum: -

NSMutableSet *set=[[NSMutableSet alloc]initWithArray:duplicateValueArray]; // will remove all the duplicate values
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.