On 17.09.2007 22:20, Jano Svitok wrote:
> On 9/17/07, Stephen Bannasch <stephen.bannasch / deanbrook.org> wrote:
>> I'm using set in the ruby standard library to produce collections of
>> unique objects from enumerable objects with duplicates but it's
>> doesn't appear to work with hash objects.
>>
>> $ ruby --version
>> ruby 1.8.5 (2006-12-25 patchlevel 12) [i686-darwin8.9.1]
>> $ irb
>> irb(main):001:0> require 'set'
>> => true
>> irb(main):002:0> a = [1,1,2,3]
>> => [1, 1, 2, 3]
>> irb(main):003:0> b = [{:a1 => "123"}, {:a1 => "123"}, {:b1 => "123"}]
>> => [{:a1=>"123"}, {:a1=>"123"}, {:b1=>"123"}]
>> irb(main):004:0> seta = a.to_set
>> => #<Set: {1, 2, 3}>
>> irb(main):005:0> setb = b.to_set
>> => #<Set: {{:a1=>"123"}, {:a1=>"123"}, {:b1=>"123"}}>
>> irb(main):006:0> b[0] == b[1]
>> => true
>>
>> Am I doing something wrong?
> 
> Your problem is in hash comparison. Set is internally using hash as
> implementation (values are keys in the hash). So in order to obtain
> uniqueness of the values, you need to define proper Hash#eq (IIRC).
> The default one is comparing object ids - i.e. two totally equivalent
> hashes are considered different.
> 
> To make things even worse, hash calls dup when creating a new key to
> avoid someone else changing the object. So even if you insert the same
> object more times, it will be added each time (resp. its copy).

This is only true for Strings - and even then only if the key is not frozen.

> For more information search the archives for something like "hash key
> dup". There were recent (as in last two months) threads that discussed
> this.

Yeah, and "Hash as Hash key" is probably another helpful search phrase. 
  This topic comes up from time to time.

Kind regards

	robert