2009-10-30 13 views
5

Piszę aplikację Ruby w tej chwili, która będzie szukać twittera dla różnych rzeczy. Jednym z problemów, przed którymi stoję, są wspólne wyniki wyszukiwania w bliskiej odległości od siebie. Wyniki są zwracane w tablicy obiektów, z których każdy jest pojedynczym tweetem. Znam metodę Array.uniq w ruby, która zwraca tablicę ze wszystkimi usuniętymi duplikatami.Usuwanie obiektów identycznych w języku Ruby?

Moje pytanie jest takie. Czy metoda uniq usuwa duplikaty, o ile te obiekty wskazują tę samą przestrzeń w pamięci lub zawierają identyczne informacje?

Jeśli to pierwszy, jaki jest najlepszy sposób usunięcia duplikatów z tablicy na podstawie ich zawartości?

Odpowiedz

10

Czy metoda uniq usunąć duplikaty o ile obiekty te wskazują tej samej przestrzeni w pamięci lub że zawierają identyczne informacje?

Metoda opiera się na metodzie eql?, więc usuwa wszystkie elementy, w których a.eql? (B) zwraca wartość true. Dokładne zachowanie zależy od konkretnego obiektu, z którym masz do czynienia.

Struny, na przykład, są uznawane za równe, jeśli zawierają ten sam tekst, niezależnie od tego, czy mają wspólny przydział pamięci.

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

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

Dotyczy to większości obiektów podstawowych, ale nie obiektów ruby.

class Foo 
end 

a = Foo.new 
b = Foo.new 

a.eql? b 
# => false 

Ruby zachęca do przedefiniowania operatora == zależności od kontekstu klasy.

W konkretnym przypadku sugerowałbym utworzenie obiektu reprezentującego wynik twittera i zaimplementowanie logiki porównania, aby Array.uniq zachowywał się zgodnie z oczekiwaniami.

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

dzięki, zaimplementowałem wymaganą metodę w klasie i wygląda na to, że działa teraz. na szczęście jedyną rzeczą, którą naprawdę muszę porównać jest unikalny identyfikator każdego tweeta :) Zakładam, że 'other.class = self.class' powinno być' other.class == self.class'? –

+0

Tak, masz rację. Naprawiony. –

+1

Nie mogłem uruchomić tej funkcji bez nadpisywania metody 'hash'. Zobacz http://www.rabbitcreative.com/2008/01/23/comparing-custom-objects-in-ruby-using-uniq/ – spier

0

wierzę, że Array.uniq wykryje duplikaty poprzez eql? lub == metod obiektów, co oznacza, porównując jej w oparciu o treść, a nie lokalizację w pamięci (zakładając, że obiekty stanowią znaczącą realizację eql? oparciu o zawartość).

6

dla nikogo innego natrafiają na to pytanie, to wygląda jak wiele się zmieniło trochę ponieważ kwestia ta została po raz pierwszy poprosił iw nowszych wersjach Ruby (1.9.3 co najmniej), Array.uniq zakłada, że ​​obiekt ma również znacząca implementacja metody #hash, oprócz .eql? lub ==.

Powiązane problemy