From: Hugh Sasse Staff Elec Eng Date: 2001-06-22T22:30:25+09:00 Subject: [ruby-talk:16763] uniq and "equivalence" Array.uniq seems to rely on deleting multiple references to the same object. Furthermore, this test for sameness seems to be based on object.id rather than == or ===. Most of the time this is right and proper, and also efficient. I support my belief that this is going on with: #!/usr/local/bin/ruby -w class Trapezoidal_fitness # Basic trapezoidal fitness funtion class # Instance vars are (upper|lower) (left|right) corners # of the tapezoid. The upper points can be co-incident # for a triangular fitness function. attr_reader :ll, :ul, :ur, :lr def initialize(ll, ul, ur, lr) @ll, @ul, @ur, @lr = ll, ul, ur, lr end def ==(other) print "in == self is #{self.inspect}, other is #{other.inspect}\n" result = (self.type == other.type) && ( (@ll == other.ll) && (@ul == other.ul) && (@ur == other.ur) && (@lr == other.lr) ) print "in == result is #{result}\n" result end def |(other) [self,other].uniq end end if __FILE__ == $0 require "runit/testcase" require 'runit/cui/testrunner' require 'runit/testsuite' class Test_Trapezoidal_fitness < RUNIT::TestCase def test_fuzzy_or first = Trapezoidal_fitness.new(99.0, 101.0, 101.0, 103.0) second = Trapezoidal_fitness.new(99.0, 101.0, 101.0, 103.0) assert_equal([first], first | second ) end end RUNIT::CUI::TestRunner.run(Test_Trapezoidal_fitness.suite) end which gives: /usr/local/lib/ruby/site_ruby/1.6/runit/assert.rb:146: warning: concat (...) interpreted as method call /usr/local/lib/ruby/site_ruby/1.6/runit/assert.rb:158: warning: concat (...) interpreted as method call Test_Trapezoidal_fitness#test_fuzzy_or F. Time: 0.002461 FAILURES!!! Test Results: Run: 1/1(1 asserts) Failures: 1 Errors: 0 Failures: 1 fit_tmp.rb:42:in `test_fuzzy_or'(Test_Trapezoidal_fitness): expected:<[#]> but was:<[#, #]> (RUNIT::AssertionFailedError) from fit_tmp.rb:46 So the | operator did not do the uniq as intended, and that can only be because the objects were deemed to be different. When this behaviour of uniq is not not what I want, how do I change it? Possible RCR: uniq and uniq! might take a block specifying an equality operator, similar to sort's comparison block. This could have applications for more complicated ideas of equivalence such as when "Sasse, Hugh", "Sasse, H. G." and "Hugh Sasse" are to be considered the same. Hugh hgs@dmu.ac.uk