2010-02-24 18 views
30

Mam klasę Foo z kilkoma zmiennymi składowymi. Gdy wszystkie wartości w dwóch instancjach klasy są równe, chcę, aby obiekty były "równe". Chciałbym wtedy, aby te obiekty były kluczami w moim haszu. Kiedy obecnie próbuję tego, skrót oznacza każdą instancję jako nierówną.Jak zrobić instancję obiektu hash w Ruby?

h = {} 
f1 = Foo.new(a,b) 
f2 = Foo.new(a,b) 

f1 i f2 powinny być równe w tym punkcie.

h[f1] = 7 
h[f2] = 8 
puts h[f1] 

należy wydrukować 8

Odpowiedz

54

Zobacz http://ruby-doc.org/core/classes/Hash.html

Hash wykorzystuje key.eql? przetestować klucze pod kątem równości . Jeśli potrzebujesz użyć instancji swoich własnych klas jako kluczy w haszowaniu, , zaleca się zdefiniowanie zarówno eql jak i . i metody mieszania. Metoda mieszania musi mieć właściwość, że a.eql? (B) implikuje a.hash == b.hash.

Eql? metoda jest łatwa do wdrożenia: zwraca wartość true, jeśli wszystkie zmienne składowe są takie same. W metodzie mieszania użyj [@ data1, @ data2] .hash, jak sugeruje Marc-Andre w komentarzach.

+0

Doskonałe wyjaśnienie. =) – Mereghost

+8

Dobrze, z wyjątkiem tego, że zwracany hash powinien być fixnum, więc lepiej użyj exclusive lub zamiast sumy (która może przepełnić do bignum). Alternatywnie użyj 'Tablica # hash', np.' [@ Data1, @ data2] .hash', say. –

+0

Dobra uwaga. Dodanie poszczególnych skrótów wiąże się również z niebezpieczeństwem, że ta sama suma może być wynikiem różnych indywidualnych skrótów (3 + 2 = 5 i 1 + 4 = 5). Korzystanie z funkcji Array # hash, jak sugeruje Marc-Andre, sprawi, że rozwiązanie będzie bardziej kompletne. – Mark

-3

Dodaj metodę zwaną „hash” do klasy:

class Foo 
    def hash 
    return whatever_munge_of_instance_variables_you_like 
    end 
end 

to będzie działać tak, jak żądany i nie będzie generować różne klawisze skrótu do różnych, ale identycznymi przedmiotami.

+4

Powinieneś również zdefiniować metodę eql? W sposób zgodny z metodą hash. Metoda hash musi zwrócić Fixnum, lub będzie break uniq. – ChrisPhoenix