2012-06-28 1 views
14

Demo (я ожидаю результат [3]):Как сделать разумную «разницу в настройках» в 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! 

И:

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

Как один для выполнения реальной установки разницы независимо от порядка входов?

Ps. В стороне, мне нужно сделать это для двух массивов с 2000 элементами. Обычно массив # 1 будет содержать меньше элементов, чем массив # 2, но это не гарантируется.

ответ

49

The - operator применяется к двум массивам a и b дает relative complement из b в a (пункты, которые находятся в a, но не в b).

То, что вы ищете, это symmetric difference двух наборов (объединение обоих относительных дополнений между ними). Это будет делать трюк:

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

Если вы работаете на Set объектов, вы можете использовать перегруженный ^ operator:

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

Для дополнительного удовольствия, вы можете также найти относительную комплемент intersection в union из двух комплектов:

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

+1, хороший ответ. Я добавил Array #^в мою [библиотеку расширений] (http://rubydoc.info/gems/shenanigans/1.0.4/Array#%5E-instance_method), не всегда нужно проходить через множества. –