" Equality—Two hashes are equal if they each contain the same
number of keys and if each key-value pair is equal to (according to
+Object#==+) the corresponding elements in the other hash."
I am having problems understanding the following:
$ irb
irb(main):001:0> VERSION
=> “1.8.5”
irb(main):002:0> a={:c => nil, :d => nil}
=> {:c=>nil, :d=>nil}
irb(main):003:0> b={:d => nil, :c => nil}
=> {:c=>nil, :d=>nil}
irb(main):004:0> # As expected this is true
irb(main):005:0* a == b
=> true
irb(main):006:0> c={:a => nil, a => nil, :b => nil}
=> {:b=>nil, :a=>nil, {:c=>nil, :d=>nil}=>nil}
irb(main):007:0> d={:b => nil, b => nil, :a => nil}
=> {:b=>nil, {:c=>nil, :d=>nil}=>nil, :a=>nil}
irb(main):008:0> # Unexpectedly false
irb(main):009:0* c == d
=> false
Apparently it’s enough for two values to be #== to one another, but
it’s not good enough for two keys to be #== to one another.
To take it one step further, think about it this way:
p c[1] == d[1]
#=> true
p e[a] == f[a]
#=> false
If you wanted the functionality you were expecting, then for these two
hashes:
x = { m=>1, n=>2, o=>3 }
y = { g=>1, h=>2, k=>3 }
testing for equality would have to do something like:
Finally, here’s a slightly better version. It’s still O(n^2) in the
worst case, but should perform much better under common circumstances
(in case someone actually needed this functionality):
class Hash
Ouch! O(n^2) performance
Bad for hashes with many keys
def sort_of_equal( other )
equal = true
self.each{ |k,v|
unless found_key = (other[k]==v)
other.each{ |k2,v2|
break if found_key = ( ( k==k2 ) && ( v==v2 ) )
}
end
equal &&= found_key
}
equal
end
end
Note that this will still not work if you have nested hashes that you
want to treat like this. You’d need to override Hash#== fully, or put
in tests based on key and value type.
Thanks Phrogz, but yes my problem would require nested hashes and
would have
to be reasonably efficient. Let me explain… I started with the
problem of comparing
sets that may have sets as members: