views:

159

answers:

2

What would be the easiest way to compare multiple arrays, and remove duplicates?

So (arrays inside arrays in this case)...

a = [[2, 1], [3, 3], [7, 2], [5, 6]]  
b = [[2, 1], [6, 7], [9, 9], [4, 3]]  
c = [[2, 1], [1, 1], [2, 2], [9, 9]]  
d = [[2, 1], [9, 9], [2, 2], [3, 1]]  

...would come out (with priority given to array a, then b, then c, then d)

a = [[2, 1], [3, 3], [7, 2], [5, 6]]  
b = [[6, 7], [9, 9], [4, 3]]  
c = [[1, 1], [2, 2]]  
d = [[3, 1]]  
A: 

Having all the arrays in one big array:

a = [[[2, 1], [3, 3], [7, 2], [5, 6]],
[[2, 1], [6, 7], [9, 9], [4, 3]],
[[2, 1], [1, 1], [2, 2], [9, 9]],
[[2, 1], [9, 9], [2, 2], [3, 1]]]

You can achieve what you want like this:

a.inject([]) do |acc, pairs|
  acc << pairs.uniq.reject{|pair| acc.flatten(1).member?(pair)}
end

Note: I am not sure from which Ruby version Array#flatten started accepting arguments.

Edit: Here's Anurag's idea, applied to inject:

a.inject([]) do |acc, pairs|
  acc << (pairs - (acc.inject(&:+) || []))
end
Mladen Jablanović
And how does this return the result b1_ wants?
jigfox
For example, by assigning the result to `a, b, c, d`. Both you and Anurag gave an answer for the case with exactly four arrays. I just generalized the answer, I thought it to be more practical that way.
Mladen Jablanović
+6  A: 

It's just set difference or subtraction and you can write it as such. Operator overloading can be a bliss :)

a is what it is.

a
[[2, 1], [3, 3], [7, 2], [5, 6]]

b = b - a
[[6, 7], [9, 9], [4, 3]]

c = c - b - a # or c - (a + b)
[[1, 1], [2, 2]]

d = d - c - b - a # or d - (a + b + c)
[[3, 1]]
Anurag
more elegant than my approach
jigfox