2011-10-12 8 views
6

Dos matrices que contienen objetos, no se vuelven a intersecar cuando se usa '&' entre las matrices. favor, eche un vistazo a la siguiente fragmento:Intersección de matriz de rubíes

ruby-1.9.2-p290 :001 > class A 
ruby-1.9.2-p290 :002?> include Comparable 
ruby-1.9.2-p290 :003?> attr_reader :key 
ruby-1.9.2-p290 :004?> def initialize(key) 
ruby-1.9.2-p290 :005?>  @key = key 
ruby-1.9.2-p290 :006?>  end 
ruby-1.9.2-p290 :007?> def <=> obj 
ruby-1.9.2-p290 :008?>  @key <=> obj.key 
ruby-1.9.2-p290 :009?>  end 
ruby-1.9.2-p290 :010?> end 
=> nil 
ruby-1.9.2-p290 :011 > class B 
ruby-1.9.2-p290 :012?> attr_reader :key 
ruby-1.9.2-p290 :013?> def initialize(key) 
ruby-1.9.2-p290 :014?>  @key = key 
ruby-1.9.2-p290 :015?>  end 
ruby-1.9.2-p290 :016?> end 
=> nil 
ruby-1.9.2-p290 :017 > A.new(1) == A.new(1) 
=> true 
ruby-1.9.2-p290 :019 > B.new(1) == B.new(1) 
=> false 
ruby-1.9.2-p290 :020 > a1 = [A.new(1), A.new(2), A.new(3)] 
=> [#<A:0x000001009e2f68 @key=1>, #<A:0x000001009e2f40 @key=2>, #<A:0x000001009e2f18 @key=3>] 
ruby-1.9.2-p290 :021 > a2 = [A.new(3), A.new(4), A.new(5)] 
=> [#<A:0x000001009d44e0 @key=3>, #<A:0x000001009d44b8 @key=4>, #<A:0x000001009d4490 @key=5>] 
ruby-1.9.2-p290 :023 > a1 | a2 
=> [#<A:0x000001009e2f68 @key=1>, #<A:0x000001009e2f40 @key=2>, #<A:0x000001009e2f18 @key=3>, #<A:0x000001009d44e0 @key=3>, #<A:0x000001009d44b8 @key=4>, #<A:0x000001009d4490 @key=5>] 
ruby-1.9.2-p290 :024 > a1 & a2 
=> [] 

no debe a1 retorno & a2:

[#<A:0x000001009e2f18 @key=3>] 

o, sólo estoy perdiendo algo ...

Respuesta

9

No, es necesario implementar la igualdad hash para Array#& y Array#| para trabajar (implementarlo solo con comparaciones normales sería O(n * m)). El aviso Array#| también devolvió el resultado incorrecto: incluye duplicados.

Tal método de la igualdad se puede implementar de esta manera:

def hash 
    @key.hash^A.hash # just to get a different hash than the key 
end 

alias eql? == 

Además, su <=> falla si el otro objeto no responde a la tecla #. == no debería fallar, debería devolver falso si los dos objetos no se pueden comparar. También es uno de esos métodos en los que no desea usar respond_to?, sino is_a?: no desea que una película sea igual a un libro porque tienen el mismo título.

def <=>(other) 
    @key <=> other.key if other.is_a? A 
end 
+0

Gracias por ayudarme a resolver esto ... ¿Necesitamos un XOR en #hash, ya que estoy comparando dos A por su #key. Creo que solo podemos mantener @ key.hash –

+0

Funcionaría, porque eql? se llamará de todos modos. El xor está ahí para evitar colisiones con la tecla del hash. Incluso def hash; 1; El final funcionaría, pero el rendimiento sería horrible. –