2013-04-24 38 views
6

tôi đang làm một hướng dẫn của Ruby ở đây: http://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/45-more-classes/lessons/105-equality_of_objectsSo sánh đối tượng tương đương trong Ruby

Nó nói khi tôi nạp chồng toán tử == rằng tôi cũng nên quá tải eql? phương pháp và phương pháp băm, vì họ là "nhanh".

Tuy nhiên, nếu tôi quá tải cả ba về cơ bản cùng một phương pháp, cách thức này nhanh hơn phương pháp kia?

+0

Liên quan: http://stackoverflow.com/questions/10257096/why-is-faster-than-eql –

+0

@SemyonPerepelitsa: Hóa ra nó không thực sự liên quan, nhưng tôi rất vui khi có thể trả lời câu hỏi khó: -) –

+0

Cảm ơn bạn đã trả lời nó! –

Trả lời

13

Trong hầu hết các trường hợp, ==eql? có kết quả tương tự. Trong một số trường hợp, eql? là nghiêm ngặt hơn ==:

42.0 == 42 # => true 
42.0.eql?(42) # => false 

Bởi vì điều này, nếu bạn xác định == có thể bạn muốn xác định eql? cũng (hoặc ngược lại).

Lựa chọn được thực hiện là lớp Hash sẽ sử dụng eql? để phân biệt giữa các khóa khác nhau, chứ không phải ==. Có thể là ==, hãy nhớ bạn, nhưng eql? đã sạch hơn.

Để tránh thực hiện các cuộc gọi tốn kém đến eql? mọi lúc, giá trị băm được tính với yêu cầu hai đối tượng là eql? phải có cùng giá trị băm. Giá trị băm đó được lưu trữ, giúp việc tra cứu trong tương lai rất dễ dàng: nếu mã băm không khớp, thì giá trị không phải là eql? ...

Vì lý do đó, bạn phải xác định theo cách hợp lý nếu bạn xác định eql? .

Lưu ý rằng việc tính giá trị băm gần như luôn đắt hơn so với so sánh với == hoặc eql?. Tuy nhiên, khi hàm băm được tính toán, kiểm tra xem các kết quả băm có rất nhanh không.

Bởi vì băm thường liên quan đến rất nhiều so sánh, việc tính toán băm tương đối đắt tiền được thực hiện một lần cho mỗi khóa, và sau đó một lần cho mỗi lần tra cứu. Hãy tưởng tượng một băm với 10 mục. Xây dựng nó sẽ liên quan đến 10 cuộc gọi đến hash, trước khi tra cứu đầu tiên thậm chí được thực hiện. Tra cứu đầu tiên sẽ tương đối nhanh chóng: một cuộc gọi đến hash, tiếp theo là so sánh rất hiệu quả các mã băm (nó thực sự nhanh hơn so với điều này, vì chúng được "lập chỉ mục"). Nếu có một trận đấu, người chơi vẫn phải thực hiện một cuộc gọi đến eql? để đảm bảo đó là một trận đấu thực sự. Thật vậy, hai đối tượng không phải là eql? có thể có cùng một giá trị băm. Sự bảo đảm duy nhất là hai đối tượng là eql? phải có cùng một giá trị băm, nhưng hai đối tượng khác nhau cũng có thể có cùng một giá trị.

Nếu bạn muốn thực hiện tương tự bằng cách sử dụng số Array thay vào đó, bạn có thể cần 10 cuộc gọi đến eql? cho mỗi lần tra cứu.

Đối với những gì nó đáng giá, tôi không nghĩ rằng mồi Ruby bạn liên kết đến là rõ ràng như nó có thể được. Nó bỏ qua thực tế rằng việc tính toán hash có thể tốn kém, do đó, nó được thực hiện chỉ khi nó có ý nghĩa, tức là khi nó là một giả định tốt rằng mỗi phần tử sẽ được so sánh nhiều lần. Hơn nữa, đó là một sự xấu hổ rằng ví dụ về một tùy chỉnh eql? nó cho phép sử dụng == để so sánh các biến mẫu. Lý tưởng nhất, nó sẽ sử dụng eql? để nhất quán, giống như cách mà các mảng là == nếu các phần tử của nó là == và các mảng là eql? nếu các phần tử của nó là eql?. Cuối cùng, nó thực sự nên đề cập đến Struct xác định phong nha ==, hasheql? cho bạn.

+0

Cảm ơn bạn đã giải thích chi tiết ở đây, điều này chắc chắn sẽ giúp xóa nó cũng – Ricky

3

Ví dụ: Array#hash nói -

Hai mảng có cùng nội dung sẽ có cùng mã băm (và sẽ so sánh bằng eql?).

Array#== nói:

Bình đẳng - Hai mảng bằng nhau nếu chúng có chứa cùng một số yếu tố và nếu mỗi phần tử là bằng (theo Object # ==) các yếu tố tương ứng trong other_ary .

Array#eql? nói

trả về true nếu bản thân và khác là cùng một đối tượng, hoặc là cả hai mảng với cùng một nội dung.

Vì vậy, theo các tài liệu hướng dẫn rõ ràng là eql? là nhanh hơn vì nó sử dụng hash giá trị, với eql?. Trong khi #== hiện hai điều -

  1. chiều dài của mảng và kiểm tra bình đẳng
  2. mỗi phần tử.
+0

Vậy tại sao không so sánh bằng cách sử dụng == thay vì eql? Có phải vì eql sử dụng mã băm mà so sánh nhanh hơn? Nó sẽ không phải trong nội bộ phải sử dụng == để so sánh hai mã băm cho anyways tương đương? – Ricky

+0

Cảm ơn bạn! Điều đó có ý nghĩa bây giờ – Ricky

+2

Câu trả lời này là sai: 'eql?' Không sử dụng giá trị 'băm' và không nhanh hơn' == '. –