Пересечение массивов Ruby

два массива, содержащие объекты, не возвращаются пересекаются при использовании " & " между массивами. Пожалуйста, взгляните на следующий фрагмент:

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
 => [] 

не стоит А1 & А2 возврата:

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

или я просто чего-то не хватает...

1 ответов


нет, вам нужно реализовать равенство хэша для Array#& и Array#| работать (реализация его только с нормальными сравнениями будет O(n * m)). Уведомление Array#| также вернул неправильный результат: он включает дубликаты.

такой метод равенства может быть реализован следующим образом:

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

 alias eql? ==

кроме того,<=> сбой, если другой объект не отвечает на #key. == не должно завершиться неудачей, он должен вернуть false, если два объекта не могут быть сравнены. Это также один из те методы, где вы не хотите использовать respond_to?, а is_a?: вы не хотите, чтобы фильм был равен книге, потому что у них есть одно и то же название.

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