2011-10-12 43 views
6

在陣列之間使用'&'時,包含對象的兩個數組不會返回相交。 請看看下面的代碼片段:紅寶石陣列交叉點

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

不應該A1 & A2回報:

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

或者,我只是失去了一些東西......

回答

9

不,你需要爲了實現Array#&Array#|的散列相等性(僅在正常比較的情況下實現它將是O(n * m))。通知Array#|也返回了錯誤的結果:它包含重複項。

這種平等方法可以實現這種方式:

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

alias eql? == 

此外,您<=>如果其他對象不以#鍵響應失敗。 ==不應該失敗,如果兩個對象不能比較,它應該返回false。這也是您不想使用respond_to?的方法之一,而是is_a?:您不希望電影與圖書相同,因爲它們碰巧擁有相同的標題。

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

感謝您幫助我弄清楚這一點......我們是否需要在#hash中進行異或運算,因爲我正在通過#key比較兩個A.我認爲,我們只能保留@key.hash –

+0

它會工作,因爲eql?將被稱爲無論如何。 xor只是爲了避免與散列鍵相沖突。即使def散列; 1;最終會奏效,但表現會很糟糕。 –