Impostare operazioni (unione, intersezione) su Swift array?


100

Esistono chiamate di libreria standard che posso utilizzare per eseguire operazioni sugli insiemi su due array o implementare personalmente tale logica (idealmente nel modo più funzionale ed efficiente possibile)?


Un set può essere implementato sopra un dizionario se vuoi farlo da solo.
CodaFi

@CodaFi Intendi usare le chiavi per garantire l'unicità?
devios1

Potresti semplicemente usare `Dictionary <String, Void>?
David Berry

Risposte:


184

Sì, Swift ha la Setclasse.

let array1 = ["a", "b", "c"]
let array2 = ["a", "b", "d"]

let set1:Set<String> = Set(array1)
let set2:Set<String> = Set(array2)

Swift 3.0+ può eseguire operazioni sui set come:

firstSet.union(secondSet)// Union of two sets
firstSet.intersection(secondSet)// Intersection of two sets
firstSet.symmetricDifference(secondSet)// exclusiveOr

Swift 2.0 può calcolare sugli argomenti dell'array:

set1.union(array2)       // {"a", "b", "c", "d"} 
set1.intersect(array2)   // {"a", "b"}
set1.subtract(array2)    // {"c"}
set1.exclusiveOr(array2) // {"c", "d"}

Swift 1.2+ può calcolare su set:

set1.union(set2)        // {"a", "b", "c", "d"}
set1.intersect(set2)    // {"a", "b"}
set1.subtract(set2)     // {"c"}
set1.exclusiveOr(set2)  // {"c", "d"}

Se stai usando strutture personalizzate, devi implementare Hashable.

Grazie a Michael Stern nei commenti per l'aggiornamento Swift 2.0.

Grazie ad Amjad Husseini nei commenti per le informazioni Hashable.


8
Nota che, almeno a partire da Swift 2.0, puoi passare un array come argomento a queste funzioni. Pertanto, set1.union(array2)e set1.exclusiveOr(array2)sono entrambi legittimi, oltre alle forme sopra indicate.
Michael Stern

E se volessi intersecare 5 array? O 6? E se il numero di array è sconosciuto?
Nathan McKaskle

2
@Nathan Dipende dall'operazione impostata. Ad esempio, l'unione degli insiemi e l'intersezione degli insiemi sono commutative e associative, quindi puoi elaborare molti insiemi utilizzando l'iterazione o il concatenamento. Oppure puoi creare metodi personalizzati che utilizzano var args, come Set union_all (...) e intersect_all (...).
joelparkerhenderson

E se i tuoi array contengono valori duplicati, ad esempio per determinare se $ 0 è un anagramma di $ 1 in cui i caratteri di input potrebbero avere lettere duplicate?
Dave Kliman

1
Se stai usando strutture personalizzate devi conformarti a Hashable, il che potrebbe essere fastidioso se hai una struttura complicata
Amjad Husseini

0

Non ci sono chiamate di libreria standard, ma potresti voler guardare la libreria ExSwift . Include un sacco di nuove funzioni sugli array, tra cui differenza, intersezione e unione.


1
Una nota di avvertimento: stavo usando ExSwift senza problemi per Swift 1.x ma sembra abbastanza rotto per Swift 2.x, e al momento della stesura di questo articolo non è stato aggiornato da pochi mesi. Ci sono un sacco di fork che potrebbero ricevere maggiore attenzione.
Robin Macharg,


0

Il metodo più efficiente che conosco è usare i numeri Godel. Google per la codifica godel.

L'idea è così. Supponiamo di avere N numeri possibili e di doverne creare insiemi. Ad esempio, N = 100.000 e vuoi creare insiemi come {1,2,3}, {5, 88, 19000} ecc.

L'idea è di tenere in memoria l'elenco di N numeri primi e per un dato insieme {a, b, c, ...} lo codifichi come

 prime[a]*prime[b]*prime[c]*...

Quindi codifichi un set come BigNumber. Le operazioni con BigNumbers, nonostante siano più lente delle operazioni con Integers, sono comunque molto veloci.

Per unire 2 set A, B, prendi

  UNITE(A, B) = lcm(a, b)

multiplo più basso comune di A e B poiché A e B sono insiemi ed entrambi i numeri.

Per fare l'incrocio che prendi

 INTERSECT(A, B) = gcd (a, b)

massimo comun divisore.

e così via.

Questa codifica è chiamata godelizzazione, puoi cercare di più su google, tutto il linguaggio dell'aritmetica scritto usando la logica di Frege può essere codificato usando i numeri in questo modo.

Per ottenere l'operazione è membro? è molto semplice -

ISMEMBER(x, S) = remainder(s,x)==0

Per ottenere il cardinale è un po 'più complicato -

CARDINAL(S) = # of prime factors in s

scomponi il numero S che rappresenta l'insieme in prodotto di fattori primi e aggiungi i loro esponenti. Nel caso in cui l'insieme non consenta duplicati avrai tutti gli esponenti 1.

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.