views:

207

answers:

1

Say I have the following hashes:

hash_x = {
  :a => 1,
  :b => 2
}
hash_y = {
  :b => 2,
  :c => 3
}

I need a chunk of logic that compares the two for equality only taking into consideration intersecting keys.

In this example the 'b' key is the only commonality between the two hashes and it's value is set to '2' in both so by that logic these two hashes would be considered equal.

Likewise these two hashes would not be equal due to the inequality of the 'd' key (the 'a' and 'c' key values are ignored since they are unique to their respective hashes):

hash_p = {
  :a => 1,
  :b => 2,
  :d => 3,
}
hash_q = {
  :b => 2,
  :c => 3,
  :d => 4
}

Is there a clever one-liner in Ruby that can calculate the intersecting keys of the two hashes then compare their values for equality based on those keys?

Bonus points if you provide tests.

More bonus points if you monkey-patch it into the Hash class.

+8  A: 
def compare_intersecting_keys(a, b)
  (a.keys & b.keys).all? {|k| a[k] == b[k]}
end

Use like this:

compare_intersecting_keys(hash_x, hash_y)  # => true
compare_intersecting_keys(hash_p, hash_q)  # => false

If you want it monkey-patched:

class Hash
  def compare_intersection(other)
    (self.keys & other.keys).all? {|k| self[k] == other[k]}
  end
end
Pesto
That's great but there's a couple edge cases I want to handle, like if one of the hashes is nil, or empty, or if the value 1 is equal to '1', or the key :b matches the key 'b'. I'll post my solution with unit tests after this simmers for a couple days. Thanks!
Teflon Ted
Where's your bonus points? I think you got ripped off! :)
tadman
@Teflon Ted: You know what's better than just stating that you have some edge cases? Posting them so they can be provided for. The two examples you give take if from being a simple one-liner to something more complex.
Pesto