From: Phrogz Date: 2006-11-01T03:30:12+09:00 Subject: Re: !x.include? y Giles Bowkett wrote: > basically, I need to filter list A to match list B. list A is a list > of objects with a particular field, and list B is a list of acceptable > values for that field. Interesting; you're basically talking about set intersection: irb(main):001:0> requested = %w|a b c x z| => ["a", "b", "c", "x", "z"] irb(main):002:0> legal = %w|a b c d e f g| => ["a", "b", "c", "d", "e", "f", "g"] irb(main):003:0> requested & legal => ["a", "b", "c"] Except that you're talking about calling considering an object equivalent to the value of one of its 'fields'. I had hoped that the following would work, but no luck: 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 eq?( o2 ); @equiv.eq?( 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 #=> [] Looking at the source code for Array#&, I see that it uses the hash value of at least one of the arrays. (And I can see that my custom hash method above is getting called.) But that's not enough. Apparently I can't even *read* C code any more, much less write it. Can someone who is more C savvy than I am tell me what the following code is doing (and thus what might be done, if anything, to allow the built-in Array#& to work with custom classes pretending to be something they aren't)? static VALUE rb_ary_and(ary1, ary2) VALUE ary1, ary2; { VALUE hash, ary3, v, vv; long i; ary2 = to_ary(ary2); ary3 = rb_ary_new2(RARRAY(ary1)->len < RARRAY(ary2)->len ? RARRAY(ary1)->len : RARRAY(ary2)->len); hash = ary_make_hash(ary2, 0); for (i=0; ilen; i++) { v = vv = rb_ary_elt(ary1, i); if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { rb_ary_push(ary3, v); } } return ary3; }