DCameronMauch
DCameronMauch

Reputation: 323

Custom comparison operator for difference between arrays in Ruby

I have two arrays of some class. I want to find the difference between them. But I want it to be based on the value of a specific method call to each instance of this class, instead of the entire instance. Here is some example code where I use Hash for the class.

#!/usr/bin/ruby

require 'awesome_print'

class Hash
  def <=> other
    puts 'space ship'
    self[:a] <=> other[:a]
  end
  def == other
    puts 'double equal'
    self[:a] == other[:a]
  end
  def > other
    puts 'greater than'
    self[:a] > other[:a]
  end
  def < other
    puts 'less than'
    self[:a] < other[:a]
  end
  def >= other
    puts 'greater equal'
    self[:a] >= other[:a]
  end
  def <= other
    puts 'less equal'
    self[:a] <= other[:a]
  end
  def eql? other
    puts 'eql?'
    self[:a].eql? other[:a]
  end
  def equal? other
    puts 'equal?'
    self[:a].equal? other[:a]
  end
end

c  = { a: 1, b: 2, c: 3}
d  = { a: 2, b: 3, c: 4}
e1 = { a: 3, b: 4, c: 5}
e2 = { a: 3, b: 4, c: 5}
e3 = { a: 3, b: 5, c: 4}
f1 = { a: 4, b: 5, c: 6}
f2 = { a: 4, b: 5, c: 6}
f3 = { a: 4, b: 6, c: 5}
g  = { a: 5, b: 6, c: 7}
h  = { a: 6, b: 7, c: 8}

a = [c, d, e1, f1]
b = [e3, f3, g, h]

ap (a - b)

I expect to see 2 elements in the final array, but still seeing 4. Tried overriding all the various comparison operators for the class of each element, Hash in this case, and I can see some calls to the 'double equal', but it still doesn't have the proper effect. What am I doing wrong?

Upvotes: 1

Views: 722

Answers (1)

J&#246;rg W Mittag
J&#246;rg W Mittag

Reputation: 369536

Array#- uses the eql? / hash protocol, just like Hash, Set and Array#uniq:

class Hash
  def eql? other
    puts 'eql?'
    self[:a].eql? other[:a]
  end
  def hash
    puts 'hash'
    self[:a].hash
  end
end

c  = { a: 1, b: 2, c: 3}
d  = { a: 2, b: 3, c: 4}
e1 = { a: 3, b: 4, c: 5}
e2 = { a: 3, b: 4, c: 5}
e3 = { a: 3, b: 5, c: 4}
f1 = { a: 4, b: 5, c: 6}
f2 = { a: 4, b: 5, c: 6}
f3 = { a: 4, b: 6, c: 5}
g  = { a: 5, b: 6, c: 7}
h  = { a: 6, b: 7, c: 8}

a = [c, d, e1, f1]
b = [e3, f3, g, h]

a - b
# => [{a: 1, b: 2, c: 3}, {a: 2, b: 3, c: 4}]

Upvotes: 1

Related Questions