2012-06-28 5 views
14

Demo (mi aspetto provocare [3]):Come fare sane "set-difference" in Ruby?

[1,2] - [1,2,3] => [] # Hmm 
[1,2,3] - [1,2] => [3] # I see 

a = [1,2].to_set => #<Set: {1, 2}> 
b = [1,2,3].to_set => #<Set: {1, 2, 3}> 
a - b    => #<Set: {}> WTF! 

E:

[1,2,9] - [1,2,3] => [9] # Hmm. Would like [[9],[3]] 

Come si fa a eseguire una differenza vera e propria serie indipendentemente dall'ordine degli ingressi?

Ps. Per inciso, ho bisogno di farlo per due array di 2000 elementi. Di solito, l'array # 1 avrà meno elementi dell'array # 2, ma questo non è garantito.

risposta

49

La - operator applicato a due array a e b dà la relative complement di b a a (elementi che sono a ma non in b).

Quello che stai cercando è il symmetric difference di due set (l'unione di entrambi i relativi complementi tra i due). Ciò farà il trucco:

a = [1, 2, 9] 
b = [1, 2, 3] 
a - b | b - a   # => [3, 9] 

Se si opera su Set oggetti, è possibile utilizzare il sovraccarico ^ operator:

c = Set[1, 2, 9] 
d = Set[1, 2, 3] 
c^d     # => #<Set: {3, 9}> 

Per divertimento extra, si potrebbe anche trovare il complemento relativa del intersection in il union dei due set:

(a | b) - (a & b) # => #<Set: {3, 9}> 
+1

+1, bella risposta. Ho aggiunto l'array #^alla mia [libreria estensioni] (http://rubydoc.info/gems/shenanigans/1.0.4/Array#%5E-instance_method), non è sempre necessario passare attraverso i set. –