2009-10-30 44 views
5

Tôi đang viết một ứng dụng Ruby tại thời điểm này sẽ tìm kiếm twitter cho nhiều thứ khác nhau. Một trong những vấn đề tôi sẽ phải đối mặt là kết quả được chia sẻ giữa các tìm kiếm gần với nhau theo thời gian. Các kết quả được trả về trong một mảng các đối tượng, mỗi đối tượng là một tweet đơn. Tôi biết phương pháp Array.uniq trong ruby ​​trả về một mảng với tất cả các bản sao đã bị loại bỏ.Xóa đối tượng giống hệt trong Ruby?

Câu hỏi của tôi là vậy. Phương thức uniq có loại bỏ các bản sao cho đến khi các đối tượng này trỏ đến cùng một không gian trong bộ nhớ hoặc chúng chứa thông tin giống nhau không?

Nếu trước đây, cách tốt nhất để xóa các bản sao khỏi một mảng dựa trên nội dung của chúng là gì?

Trả lời

10

Liệu phương pháp uniq loại bỏ bản sao trong chừng mực các đối tượng này trỏ đến cùng một không gian trong bộ nhớ hoặc là họ chứa thông tin giống hệt nhau?

Phương pháp dựa vào phương pháp eql? để nó loại bỏ tất cả các yếu tố trong đó a.eql? (B) trả về giá trị đúng. Hành vi chính xác phụ thuộc vào đối tượng cụ thể mà bạn đang xử lý. Ví dụ:

Chuỗi được coi là bằng nhau nếu chúng chứa cùng một văn bản bất kể chúng phân chia cùng một phân bổ bộ nhớ.

a = b = "foo" 
c = "foo" 

[a, b, c].uniq 
# => ["foo"] 

Điều này đúng với hầu hết các đối tượng chính nhưng không dành cho các đối tượng ruby.

class Foo 
end 

a = Foo.new 
b = Foo.new 

a.eql? b 
# => false 

Ruby khuyến khích bạn xác định lại nhà điều hành == tùy thuộc vào ngữ cảnh lớp học của bạn.

Trong trường hợp cụ thể của bạn, tôi sẽ đề xuất tạo đối tượng đại diện cho kết quả twitter và triển khai logic so sánh của bạn sao cho Array.uniq sẽ hoạt động như bạn mong đợi.

class Result 

    attr_accessor :text, :notes 

    def initialize(text = nil, notes = nil) 
    self.text = text 
    self.notes = notes 
    end 

    def ==(other) 
    other.class == self.class && 
    other.text == self.text 
    end 
    alias :eql? :== 

end 

a = Result.new("first") 
b = Result.new("first") 
c = Result.new("third") 

[a, b, c].uniq 
# => [a, c] 
+0

cảm ơn, tôi đã triển khai phương pháp được yêu cầu trong lớp và có vẻ như giờ đây bạn đang làm việc. may mắn là điều duy nhất tôi thực sự cần so sánh là ID duy nhất cho mỗi tweet :) Tôi đoán rằng 'other.class = self.class' phải là' other.class == self.class'? –

+0

Có, bạn đã đúng. Đã sửa. –

+1

Tôi không thể làm việc này mà không ghi đè phương thức 'băm'. Xem http://www.rabbitcreative.com/2008/01/23/comparing-custom-objects-in-ruby-using-uniq/ – spier

0

Tôi tin rằng Array.uniq phát hiện bản sao qua eql? hoặc == phương pháp của các đối tượng, có nghĩa là so sánh dựa trên nội dung, không phải vị trí của nó trong bộ nhớ (giả định các đối tượng cung cấp một thực hiện ý nghĩa của eql? dựa trên nội dung).

6

Đối với bất cứ ai khác ngại khi câu hỏi này, có vẻ như mọi thứ đã thay đổi một chút kể từ khi câu hỏi này lần đầu tiên được hỏi và trong các phiên bản của Ruby mới hơn (1.9.3 ít nhất), Array.uniq giả định rằng đối tượng của bạn cũng có một triển khai có ý nghĩa phương pháp #hash, ngoài .eql? hoặc ==.

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