2010-02-24 38 views
30

Tôi có một lớp Foo với một vài biến thành viên. Khi tất cả các giá trị trong hai trường hợp của lớp đều bằng nhau, tôi muốn các đối tượng được 'bằng nhau'. Sau đó tôi muốn các đối tượng này là chìa khóa trong băm của tôi. Khi tôi đang thử điều này, hàm băm xử lý từng trường hợp là không bằng nhau.Làm thế nào để tạo đối tượng dụ một khóa băm trong Ruby?

h = {} 
f1 = Foo.new(a,b) 
f2 = Foo.new(a,b) 

f1 và f2 phải bằng nhau tại thời điểm này.

h[f1] = 7 
h[f2] = 8 
puts h[f1] 

nên in 8

Trả lời

54

Xem http://ruby-doc.org/core/classes/Hash.html

Hash sử dụng key.eql? để kiểm tra các khóa cho số bình đẳng. Nếu bạn cần sử dụng các cá thể của riêng bạn làm khóa trong Hash, , bạn nên xác định cả hai eql? và phương thức băm. Phương thức băm phải có thuộc tính là a.eql? (B) ngụ ý a.hash == b.hash.

Eql? phương thức dễ thực hiện: trả về true nếu tất cả các biến thành viên đều giống nhau. Đối với phương thức băm, sử dụng [@ data1, @ data2] .hash như Marc-Andre gợi ý trong phần bình luận.

+0

Giải thích hoàn hảo. =) – Mereghost

+8

Tốt, ngoại trừ hàm băm trả về phải là một bản sửa lỗi, vì vậy tốt hơn nên sử dụng độc quyền hoặc thay vì tổng (có thể tràn vào bignum). Ngoài ra, sử dụng 'mảng # băm', như' [@ data1, @ data2] .hash', nói. –

+0

Điểm tốt. Việc thêm các băm riêng lẻ với nhau cũng có nguy cơ mà cùng một tổng có thể phát sinh từ các băm riêng lẻ khác nhau (3 + 2 = 5 và 1 + 4 = 5). Sử dụng mảng # hash như Marc-Andre gợi ý sẽ làm cho giải pháp hoàn chỉnh hơn. – Mark

-3

Thêm một phương pháp gọi là 'băm' đến lớp học của bạn:

class Foo 
    def hash 
    return whatever_munge_of_instance_variables_you_like 
    end 
end 

này sẽ làm việc theo cách mà bạn yêu cầu và sẽ không tạo ra các phím băm khác nhau cho các đối tượng khác nhau, nhưng giống hệt nhau,.

+4

Bạn cũng nên định nghĩa phương thức eql? Theo cách thức phù hợp với phương thức băm, phương thức băm phải trả về một Fixnum, hoặc nó sẽ ngắt uniq. – ChrisPhoenix

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