From: Phrogz Date: 2006-11-02T03:50:19+09:00 Subject: Re: !x.include? y Phrogz wrote: > I had hoped that the following would work, but no luck: [snip] The reason that what I posted didn't work is because I mispelled 'eql?' as 'eq?'. Oops. Following is code that does actually work: class Object def equiv; self; end end class Equiv def self.[]( data, equiv ) self.new( data, equiv ) end attr_accessor :data, :equiv def initialize( data, equiv ) @data, @equiv = data, equiv end def <=>( o2 ); @equiv <=> o2.equiv end def == ( o2 ); @equiv == o2.equiv end def ===( o2 ); @equiv === o2.equiv end def eql?( o2 ); @equiv.eql?( o2.equiv ) end def hash; @equiv.hash end end possible = [ Equiv[ 1001, 'a' ], Equiv[ 1002, 'b' ], Equiv[ 1003, 'c' ], Equiv[ 2098, 'x' ], Equiv[ 3143, 'z' ] ] legal = %w|a b c d e f g| p possible & legal #=> [#, #, #] So, going back to the original problem (which has long since been solved), we can do this instead: require 'equiv' objs_as_attributes = list.map{ |obj| Equiv[ obj, obj.attribute ] } acceptable_obj_wrappers = objs_as_attributes & list_of_acceptable_values acceptable_objs = acceptable_obj_wrappers.map{ |eq| eq.data } Obviously that's too much work. I smell an interesting approach for automatically treating one type of object as another: module Enumerable def treat_as( method ) result = yield map{|obj| Equiv[obj, obj.send(method)]} if result.is_a? Equiv result.data else result.map{ |obj| obj.is_a?( Equiv ) ? obj.data : obj } end end end Person = Struct.new( :name, :age ) people = [ Person.new( 'Gavin', 33 ), Person.new( 'Bob', 35 ), Person.new( 'Jim', 40 ), Person.new( 'Lisa', 32 ), Person.new( 'Sam', 30 ) ] legal_ages = [ 32, 33 ] legal_people = people.treat_as( :age ){ |people_as_ages| people_as_ages & legal_ages } p legal_people #=> [#, #] oldest = people.treat_as( :age ){ |people_as_ages| people_as_ages.max } p oldest #=> # This smells wrong applying only to Enumerables, but I'm too busy to really think this through. Just thought I'd share the idea.