Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare arrays and remove duplicates, in Ruby?

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]]  
like image 609
b1_ Avatar asked Dec 07 '22 02:12

b1_


2 Answers

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]]
like image 195
Anurag Avatar answered Dec 24 '22 17:12

Anurag


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
like image 34
Mladen Jablanović Avatar answered Dec 24 '22 18:12

Mladen Jablanović