Quando è meglio usare un NSSet su un NSArray?


Risposte:


173

Quando l'ordine degli elementi nella raccolta non è importante, i set offrono prestazioni migliori per la ricerca di elementi nella raccolta.

Il motivo è che un set usa valori hash per trovare elementi (come un dizionario) mentre un array deve iterare su tutto il suo contenuto per trovare un particolare oggetto.


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

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

1
Se ordinato: O (1) vs O (logn) poiché è applicabile la ricerca binaria. Se non ordinato, allora O (1) vs O (n)
baskInEminence

180

L'immagine dalla documentazione di Apple lo descrive molto bene:

Collezioni Objective-C

Arrayè una sequenza di elementi ordinata (l'ordine viene mantenuto quando si aggiunge)

[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è un elenco di elementi distinto (senza duplicati) e non ordinato

[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
Nel tuo esempio, stai aggiungendo primitive a un array e a un set. Nessuno dei due è possibile perché possono contenere solo oggetti.
FreeAsInBeer

10
Grazie per la tua modifica @Zaheer, ma in realtà non era valida. Non stavo aggiungendo primitive. Stavo aggiungendo letterali.
James Webster

Ottima spiegazione :) +1 :)
Karun

1
Adoro la tua spiegazione! +1 per quello
ribellione

66

La migliore risposta a questa domanda è la documentazione di Apple .

inserisci qui la descrizione dell'immagine

La differenza principale è che NSArrayè per una raccolta ordinata e NSSetper una raccolta non ordinata.

Ci sono diversi articoli là fuori che parlano della differenza di velocità tra i due, come questo . Se stai iterando attraverso una raccolta non ordinata, NSSetè fantastico. Tuttavia, in molti casi, devi fare cose che solo un NSArraypuò fare, quindi sacrifichi la velocità per quelle abilità.

NSSet

  • Accedi principalmente agli articoli per confronto
  • non ordinato
  • Non consente duplicati

NSArray

  • Può accedere agli elementi per indice
  • Ordinato
  • Consente duplicati

Questo è tutto ciò che c'è davvero da fare! Fammi sapere se aiuta.


Non devi sempre sacrificarti NSSetper il bene dell'indicizzazione. È comune utilizzare due diverse strutture di dati per gli stessi dati. Oppure si crea e si indicizza su quell'array :) Ma poi è meglio usare un DB che lo abbia già implementato.
Sulthan

"Costruisci un indice su quell'array". Non è possibile creare un indice su un NSSet. Esistono molte tecniche diverse che puoi utilizzare. E se hai bisogno di fare sacrifici SIA nella memoria che nella potenza di elaborazione, lo stai facendo in modo sbagliato.
Sulthan

Poiché la domanda riguarda NSSete NSArray, la mia risposta è accurata e completa. Sì, puoi creare altre strutture di dati, ma sto solo confrontando queste due.
woz

Ho votato positivamente ma la tua risposta è sbagliata quando parli di sacrifici. Se hai bisogno di alcune funzionalità NSArraye di alcune funzionalità NSSet, la risposta corretta non è "usa NSArraye sacrifica le prestazioni". La risposta è combinare entrambi o utilizzare una struttura dati diversa.
Sulthan

Avrei detto che la differenza principale è impostata per oggetti unici in cui un array può avere duplicati. L'aspetto dell'ordine è secondario rispetto a questo fatto.
malhal

12

NSOrderedSet è disponibile in iOS 5+, quindi la differenza principale è se vuoi oggetti duplicati nella struttura dei dati.


9

NSArray :

  1. Raccolta di dati ordinata
  2. Consente duplicati
  3. È un oggetto di tipo raccolta

NSSet :

  1. Raccolta di dati non ordinata
  2. Non consente duplicati
  3. È anche un oggetto di tipo raccolta

7

Un array viene utilizzato per accedere agli elementi in base al loro indice. Qualsiasi elemento può essere inserito più volte nell'array. Gli array mantengono l'ordine dei loro elementi.

Un set viene utilizzato fondamentalmente solo per verificare se l'elemento è nella collezione o meno. Gli articoli non hanno il concetto di ordine o indicizzazione. Non puoi avere un oggetto in un set due volte.

Se un array vuole controllare se contiene un elemento, deve controllare tutti i suoi elementi. I set sono progettati per utilizzare algoritmi più veloci.

Puoi immaginare un insieme come un dizionario senza valori.

Notare che array e set non sono le uniche strutture di dati. Ce ne sono altri, ad esempio Queue, Stack, Heap, Fibonacci's Heap. Consiglierei di leggere un libro sugli algoritmi e le strutture dati.

Vedi wikipedia per maggiori informazioni.


In realtà, un array deve essere controllato solo fino al punto in cui l'elemento viene trovato. Se l'elemento è nella matrice, molto raramente sarà necessario controllare ogni elemento.
FreeAsInBeer

Sì, come dici tu "se l'elemento È nella matrice". Se ti aspetti questo, non devi controllare se è presente o meno. La complessità containsdell'operazione è O(n). Il numero di confronti quando non è nell'array è n. Il numero medio di confronti quando l'oggetto è nella matrice è n/2. Anche se l'oggetto viene trovato, la prestazione è terribile.
Sulthan

Le prestazioni sarebbero terribili solo con una vasta gamma. Se si sapeva che l'array potrebbe diventare piuttosto grande, ci sono modi per migliorare le prestazioni dell'array, come l'utilizzo di un array di array.
FreeAsInBeer

Se l'operazione di uguaglianza è costosa, vedrai la differenza anche su array con 3 elementi. E lo stesso comportamento di un array di grandi dimensioni può verificarsi quando si ripete spesso l'operazione (ad esempio, utilizzare l'operazione in un ciclo "for"). Hai sentito parlare della complessità ammortizzata? La complessità è ancora lineare e le prestazioni sono terribili rispetto a un set (di solito con complessità costante).
Sulthan

Ovviamente ci sarà una differenza, sto solo affermando che la grande notazione o è esponenziale; con piccoli array, la differenza sarà minuscola. Inoltre, NSArrays ha altri vantaggi in termini di velocità rispetto a NSSets. Come sempre, è un compromesso.
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);

l'array

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

il set

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


4

Le principali differenze sono già state fornite in altre risposte.

Vorrei solo notare che a causa del modo in cui i set e i dizionari sono implementati (cioè usando gli hash), si dovrebbe fare attenzione a non usare oggetti mutabili per le chiavi.

Se una chiave viene modificata, anche l'hash cambierà (probabilmente), indicando un indice / bucket diverso nella tabella hash. Il valore originale non verrà eliminato e verrà effettivamente preso in considerazione quando si enumera o si chiede alla struttura la sua dimensione / conteggio.

Questo può portare ad alcuni bug davvero difficili da individuare.


3

Qui puoi trovare un confronto abbastanza approfondito delle strutture di dati NSArraye NSSet.

Brevi conclusioni:

Sì, NSArray è più veloce di NSSet per il semplice mantenimento e l'iterazione. Fino al 50% più veloce per la costruzione e fino al 500% più veloce per l'iterazione. Lezione: se hai solo bisogno di iterare i contenuti, non usare un NSSet.

Ovviamente, se devi testare l'inclusione, lavora sodo per evitare NSArray. Anche se hai bisogno sia di iterazione che di test di inclusione, dovresti comunque scegliere un NSSet. Se è necessario mantenere la raccolta ordinata e anche testarne l'inclusione, è opportuno considerare di conservare due raccolte (un NSArray e un NSSet), ciascuna contenente gli stessi oggetti.

NSDictionary è più lento da costruire rispetto a NSMapTable, poiché deve copiare i dati chiave. Compensa ciò essendo più veloce nella ricerca. Naturalmente, i due hanno capacità diverse, quindi la maggior parte delle volte questa determinazione dovrebbe essere fatta su altri fattori.


Sebbene questo possa teoricamente rispondere alla domanda, sarebbe preferibile includere qui le parti essenziali della risposta e fornire il collegamento per riferimento.
Tunaki

2

In genere si utilizza un Set quando la velocità di accesso è essenziale e l'ordine non è importante o è determinato con altri mezzi (tramite un predicato o un descrittore di ordinamento). Core Data, ad esempio, utilizza set quando si accede agli oggetti gestiti tramite una relazione a molti


1

Solo per aggiungerne un po ', a volte uso set solo per rimuovere i duplicati dall'array come: -

NSMutableSet *set=[[NSMutableSet alloc]initWithArray:duplicateValueArray]; // will remove all the duplicate values
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.