Цитата Дня. Полярного...

Tux Jedi


"If you fuck up OpenBSD it gets unsecure. Linux must be fucked up to be secure. Windows must be erased to be secure."

Friday, November 21, 2008

Getting Ruby Array.uniq! work for array of objects

Иногда возникает задача удалить дубликаты из массива объектов. В Ruby для решения этой задачи в классе Array есть методы uniq и uniq!. Отличие первого от второго состоит лишь в том, что второй производит in place модификацию массива, а первый возвращает результат в виде массива. Для того, чтобы эти методы работали для custom классов необходимо чтобы у классов были определены методы hash и eql?.

class TestClass

attr_reader :a, :b, :c

#Ctor

def initialize(a,b,c)
@a, @b, @c = a, b, c
end


def hash
"#@a #@b #@c".hash
end

def ==(p)
@a ==p.a and @b == p.b and @c == p.c
end

def eql?(p)
self == p
end

def to_s
"#@a,#@b,#@c"
end
end

a = []
a << TestClass.new(1,2,3)
a << TestClass.new(1,2,3)
a << TestClass.new(3,2,1)
a << TestClass.new(3,2,3)
a << TestClass.new(2,3,3)

a.uniq!

a.each do |elem|
p elem.to_s
end

Т.е. одного eql? не достаточно, как это указано в PickAxe а нужен еще и hash method который должен возвращать целое число. И чтобы я делал, если бы не USENET?

Update 20:10: тут меня коллеги попинали чуток, так что слегка изменил пример ;-). И почему мне сразу в голову не пришла мысль, что String.hash есть?

Update 25/11/2008: в ri Hash собственно нашлось объяснение :) : +Hash+ uses +key.eql?+ to test keys for equality. If you need to use instances of your own classes as keys in a +Hash+, it is recommended that you define both the +eql?+ and +hash+ methods. The +hash+ method must have the property that +a.eql?(b)+ implies +a.hash == b.hash+.

4 комментария(ев):

Fester said...

Вот такие вот нестыковки меня периодически просто убивают. Хотя в целом, язык великолепный.

Yuriy Volkov said...

да ну в принципе терпимо, если интернет под рукой есть =)

Fester said...

Ну, терпеть можно многое. Я надеюсь, что в Rubinius (на который я возлагаю много надежд) многие из таких вот вещей вылечат. Ну и, конечно, Matz суров. Делать Array#uniq через Hash...

Yuriy Volkov said...

Делать Array#uniq через Hash
Я думаю он тут руководствовался вопросами эффективности

Post a Comment

СООБЩЕНИЕ СПАМЕРАМ: прежде чем пытаться оставить ссылку на свой ресурс в комментарии, прошу обратить внимание на тег nofollow, которым они помечены и зря не терять ни свое ни мое время. А будете упорствовать еще и noindex поставлю