2011-10-12 33 views
6

Hai mảng chứa đối tượng, không trả về giao nhau khi sử dụng '&' giữa các mảng. Xin hãy nhìn vào đoạn mã dưới đây:Giao điểm mảng 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 
=> [] 

không nên a1 trở & a2:

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

hay, tôi chỉ thiếu một cái gì đó ...

Trả lời

9

Không, bạn cần để thực hiện bình đẳng băm cho Array#&Array#| để hoạt động (chỉ thực hiện nó với các so sánh thông thường sẽ là O(n * m)). Thông báo Array#| cũng trả lại kết quả sai: nó bao gồm các bản sao.

phương pháp bình đẳng như vậy có thể được thực hiện theo cách này:

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

alias eql? == 

Ngoài ra, <=> của bạn thất bại nếu đối tượng khác không đáp ứng với #key. == không nên thất bại, nó sẽ trả về false nếu hai đối tượng không thể so sánh được. Nó cũng là một trong những phương pháp mà bạn không muốn sử dụng respond_to?, nhưng thay vì is_a?: bạn không muốn một bộ phim bằng một cuốn sách vì chúng có cùng một tiêu đề.

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

Cảm ơn bạn đã giúp tôi tìm ra điều này ... Chúng tôi có cần XOR trong #hash không, vì tôi đang so sánh hai A bằng #key. Tôi nghĩ rằng, chúng tôi có thể giữ chỉ @ key.hash –

+0

Nó sẽ làm việc, bởi vì eql? sẽ được gọi là anyway. Các xor là chỉ có để tránh va chạm với khóa của băm. Ngay cả băm def; 1; kết thúc sẽ hoạt động, nhưng hiệu suất sẽ rất khủng khiếp. –

Các vấn đề liên quan