Uniquify an array of hashes in Ruby

Array#uniq is a handy Ruby method that produces an array of distinct elements. So, for example, [1,2,3,3,3].uniq produces [1,2,3].

However, this fails on an array of hashes. For example, [{}, {}].uniq actually produces [{},{}]. That’s not what I wanted, recently.

It turns out that #uniq uses the methods #hash and #eql? to determine uniqueness, and Hash#hash produces the object_id, and {}.eql?({}) produces false.

To solve this, I redefined #hash and #eql? for the hash instances before I put them in the array:


h = {}
class <<h
  def hash
    values.inject(0) { |acc,value| acc + value.hash }
  end

  def eql?(a_hash)
    self == a_hash
  end
end

It should be noted that calling #dup on this hash will then screw things up, but that’s common to all Ruby eigenclass fun.

However, you could just use a proper class instead of a hash, ’cause this isn’t Perl.

One Comment

  1. Eric
    Posted January 5, 2009 at 7:48 am | Permalink

    Thanks a lot, I needed this for this problem:
    http://projecteuler.net/index.php?section=problems&id=109 :D


One Trackback/Pingback

  1. [...] this post, Mike Burns solve this problem by redefining #hash and #eql?. If you are doing this kind of [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*