Alle luned17 settembre 2007, Stephen Bannasch ha scritto: > 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? According to the ri documentation, Set internally stores items in a hash. Because of this, it uses the eql? and hash methods, and not ==, to test objects for equality. Hash#eql? (actually, Kernel#eql?) only returns true if two objects are the same object. Since b[0] and b[1] are different objects, Set considers them not equal, and thus stores them both. If you put the same hash in two places of the array you convert to a set, only one of them will be kept: irb: 001> require 'set' true irb: 002> h = {'a' => 1, 'b' => 2} {"a"=>1, "b"=>2} irb: 003> a = [h, {'c' => 3}, h] [{"a"=>1, "b"=>2}, {"c"=>3}, {"a"=>1, "b"=>2}] irb: 004> a.to_set.size 2 irb: 005> p a.to_set #<Set: {{"a"=>1, "b"=>2}, {"c"=>3}}> Other classes, instead, provide their own definition of eql?, which leads to different (often less surprising) results. For instance, Array#eql? returns true if the two arrays have the same elements. String do the same. I hope this helps Stefano