Удаление идентичных объектов в Ruby? - PullRequest
5 голосов
/ 30 октября 2009

Я сейчас пишу приложение на Ruby, которое будет искать в твиттере разные вещи. Одна из проблем, с которыми я столкнусь, - это совместное использование результатов поиска в непосредственной близости друг от друга по времени. Результаты возвращаются в массиве объектов, каждый из которых представляет собой один твит. Я знаю метод Array.uniq в ruby, который возвращает массив со всеми удаленными дубликатами.

Мой вопрос такой. Удаляет ли метод uniq дубликаты, если эти объекты указывают на одно и то же пространство в памяти или они содержат одинаковую информацию?

Если первое, каков наилучший способ удаления дубликатов из массива на основе их содержимого?

Ответы [ 4 ]

10 голосов
/ 30 октября 2009

Удаляет ли метод uniq дубликаты? поскольку эти объекты указывают на то же пространство в памяти или что они содержать идентичную информацию?

Метод основан на методе eql?, поэтому он удаляет все элементы, для которых a.eql? (B) возвращает true. Точное поведение зависит от конкретного объекта, с которым вы имеете дело.

Например, строки считаются равными, если они содержат один и тот же текст, независимо от того, имеют ли они одинаковое распределение памяти.

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

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

Это верно для большей части основных объектов, но не для объектов ruby.

class Foo
end

a = Foo.new
b = Foo.new

a.eql? b
# => false

Ruby рекомендует переопределить оператор == в зависимости от контекста вашего класса.

В вашем конкретном случае я бы предложил создать объект, представляющий результат в Твиттере, и реализовать логику сравнения, чтобы Array.uniq вел себя так, как вы ожидаете.

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]
6 голосов
/ 23 февраля 2012

Для всех, кто сталкивается с этим вопросом, похоже, что вещи немного изменились с тех пор, как этот вопрос был задан впервые, и в более новых версиях Ruby (по крайней мере, 1.9.3) Array.uniq предполагает, что ваш объект также имеет значимую реализацию метода #hash, в дополнение к .eql? или ==.

2 голосов
/ 30 октября 2009

uniq использует eql?, как описано в этой теме .

См. официальную рубиновую документацию для различия между ==, equal? и eql?.

0 голосов
/ 30 октября 2009

Я считаю, что Array.uniq обнаруживает дубликаты с помощью методов eql? или == объектов, что означает их сравнение на основе содержимого, а не расположения в памяти (при условии, что объекты обеспечивают значимую реализацию eql? на основе содержание).

...