Die Programmiersprache Ruby (German Edition)
Schlüssel zu berechnen, die keinen zugewiesenen Wert haben:
# Wenn der Schlüssel nicht definiert ist, liefere den Nachfolger zurück
plus1 = Hash.new {|hash, key| key.succ }
plus1[1] # 2
plus1["one"] # "onf": siehe String.succ
plus1.default_proc # Gibt die Prozedur zurück, die den Standardwert berechnet
plus1.default(10) # => 11: Standard zurückgegeben für 10
Wenn man einen Standardblock wie hier verwendet, ist es üblich, den berechneten Wert mit dem Schlüssel zu verbinden, so dass die Berechnung nicht erneut durchgeführt werden muss, wenn der Schlüssel nochmals gesucht wird. Dies ist eine einfach zu implementierende Form der verzögerten Auswertung (und es erklärt, warum dem Standardblock das Hash-Objekt selbst zusammen mit dem Schlüssel übergeben wird):
# Dieser verzögert initialisierte Hash bildet Integer-Werte auf ihre Fakultäten ab
fact = Hash.new {|h,k| h[k] = if k > 1: k*h[k-1] else 1 end }
fact # {}: Hash beginnt leer
fact[4] # 24: 4! is 24
fact # {1=>1, 2=>2, 3=>6, 4=>24}: der Hash hat jetzt Einträge
Beachten Sie, dass das Setzen der Eigenschaft
default
eines Hash einen dem Konstruktor
Hash.new
übergebenen Block überschreibt.
Wenn Sie nicht an Standardwerten für einen Hash interessiert sind oder sie mit ihrem eigenen Standardwert überschreiben wollen, verwenden Sie die Methode
fetch
, um die Werte auszulesen, statt eckige Klammern zu nutzen.
fetch
wurde schon behandelt:
fact.fetch(5) # IndexError: Schlüssel nicht gefunden
9.5.3.8 Hashcodes, Schlüsselgleichheit und veränderbare Schlüssel
Damit ein Objekt als Hash-Schlüssel genutzt werden kann, muss es eine Methode
hash
besitzen, die einen Integer-»Hashcode« für das Objekt zurückliefert. Klassen, die ihre eigene Methode
eql?
definieren, können einfach die von
Object
geerbte
hash
-Methode verwenden. Wenn Sie eine Methode
eql?
zum Testen auf Objektgleichheit definieren, müssen Sie allerdings eine passende
hash
-Methode definieren. Wenn zwei verschiedene Objekte als gleich betrachtet werden, müssen ihre
hash
-Methoden denselben Wert zurückliefern. Idealerweise sollten zwei Objekte, die nicht gleich sind, unterschiedliche Hashcodes besitzen. Dieses Thema wurde in „3.4.2 Hash-Codes, Gleichheit und veränderliche Schlüssel“ behandelt; „7.1.9 Point und Gleichheit“ enthält eine Beispielimplementierung von
hash
.
Normalerweise verwenden Hashes
eql?
, um die Gleichheit von Hash-Schlüsseln zu prüfen. In Ruby 1.9 können Sie allerdings auch
compare_by_identity
für ein
Hash
-Objekt aufrufen, um stattdessen einen Schlüsselvergleich über
equal?
zu erzwingen. Wenn Sie das tun, wird der Hash auch
object_id
als Hashcode für ein Objekt verwenden. Beachten Sie, dass
compare_by_identity
eine Instanzmethode ist, die nur das aufgerufene
Hash
-Objekt beeinflusst. Einmal aufgerufen gibt es keine Möglichkeit, einen Hash in sein normales Vergleichsverhalten zurückzuführen. Verwenden Sie das Prädikat
compare_by_identity?
, um zu ermitteln, ob ein gegebener Hash auf Gleichheit oder auf Identität prüft. Denken Sie daran, dass zwei Symbolliterale mit den gleichen Zeichen in dasselbe Objekt ausgewertet werden, aber zwei String-Literale mit den gleichen Zeichen zu verschiedenen Objekten werden. Daher können Symbolliterale als Hash-Schlüssel genutzt werden, wenn über die Identität verglichen wird, String-Literale aber nicht.
Wie in „3.4.2 Hash-Codes, Gleichheit und veränderliche Schlüssel“ erwähnt wurde, müssen Sie vorsichtig sein, wenn Sie ein veränderbares Objekt als Hash-Schlüssel verwenden. (Strings sind ein Sonderfall: Die Klasse
Hash
erzeugt eine private, interne Kopie von String-Schlüsseln.) Wenn Sie veränderbare Schlüssel nutzen und einen von ihnen tatsächlich verändern, müssen Sie
rehash
für das
Hash
-Objekt aufrufen, um sicherzustellen, dass alles noch richtig funktioniert:
key = {:a=>1} # Dieser Hash wird ein Schlüssel in einem anderen Hash!
h = { key => 2 } # Dieser Hash hat einen veränderbaren Schlüssel
h[key] # => 2: mit Schlüssel verbundenen Wert holen
key.clear # Schlüssel verändern
h[key] # => nil: kein Wert für den veränderten Schlüssel gefunden
h.rehash # Hash nach der Veränderung reparieren
h[key] # => 2: jetzt wird der Wert wieder gefunden
9.5.3.9 Verschiedene Hash-Methoden
Die Methode
invert
passt in keine der vorigen Kategorien. Sie vertauscht Schlüssel und Werte in einem Hash:
h = {:a=>1, :b=>2}
h.invert # => {1=>:a, 2=>:b}: vertausche Schlüssel und Werte
Wie bei
Array
ist
Weitere Kostenlose Bücher