Eine Hashtabelle (in Smalltalk: Dictionary) ist ein Sammlung von Schlüssel-Wert-Paaren. Für ihre Erzeugung gibt es folgende Möglichkeiten:
h = {"a"=>1, "b"=>2, "c"=>3}
i = {"d"=>4}
i["e"] #-> nil
j = Hash.new("gibt's nicht")
j["e"] #-> "gibt's nicht"
i.update(h)
i #-> {"d"=>4, "a"=>1, "b"=>2, "c"=>3}
i.replace(h)
i #-> {"a"=>1, "b"=>2, "c"=>3}
Hash-Literale zur Initialisierung von Hashes werden in geschweifte Klammern
{} geschrieben. Der Zugriff auf die Hashelemente erfolgt aber immer,
indem der Schlüssel des zu suchenden Wertes in eckige Klammern []
gesetzt wird.
Das Argument der new-Methode wird als Defaultwert
genutzt. Sollte ein Schlüssel vom Hash angefordert werden, der nicht
enthalten ist, wird der Defaultwert zurückgegeben.
Ab Ruby 1.7.2 (10.12.2001) kann als Argument auch ein Block übergeben werden,
der ausgewertet wird, wenn die Hashtabelle das gewünschte Element noch nicht
enthält.
euro = Hash.new { |h, dm| h[dm] = dm*1.95583 }
euro[100] #-> 195.583
In älteren Ruby-Versionen kann man sich mit ||= behelfen:
euro = Hash.new def getEuro(dm) euro[dm] ||= dm*1.95583 end
Wie bei Arrays wird mit clear die Hashtabelle geleert.
Die Methode update fügt
die Inhalte der übergebenen Hashtabelle ein, wobei die Werte von schon
vorhandenen Schlüsseln ersetzt werden.
h1 = {"a"=>100, "b"=>110} #-> {"a"=>100, "b"=>110}
h2 = {"b"=>120, "c"=>130} #-> {"b"=>120, "c"=>130}
h1.update(h2) #-> {"a"=>100, "b"=>120, "c"=>130}
replace ersetzt den Inhalt der vorhandenen Hashtabelle. Dabei
werden alle Schlüssel-Wert-Paare ersetzt!
Hashtabellen können beliebige Objekte als Werte enthalten,
die Schlüssel sollten eine gewisse Beständigkeit besitzen:
Solange sie als Schlüssel verwendet werden, sollte sich der
Wert ihrer hash-Methode nicht ändern, um einen dauerhaften
Zugriff auf die Hashelemente zu gewährleisten.
Daher muss man insbesondere bei Arrays und Hashtabellen vorsichtig
sein, wenn man sie als Schlüssel verwenden möchte, da
sich ihr hash-Wert bei Manipulationen ihrer Elemente ändert.
a = [1, 2, 3] #-> [1, 2, 3]
a.hash #-> 25
h = { a=>"gefunden" }
h[a] #-> "gefunden"
a.shift
a.hash #-> 5
h[a] #-> nil
h.rehash
h[a] #-> "gefunden"
Mit rehash werden alle in der Hashtabelle gespeicherten
Hashwerte neu berechnet, was ziemlich viel Rechenzeit kosten kann,
wenn die Hashtabelle größer wird.
Bei den besonders häufig als Schlüssel verwendeten Strings setzt Ruby automatisch eine Kopie des Schlüsselstrings in die Hashtabelle ein, um dieses Problem zu vermeiden.
s = "foo"
s.hash #-> 876516207
hash = { s => "bar" } #-> {"foo" -> "bar"}
s[1,2] = "uu"
s #-> "fuu"
s.hash #-> 876922107
hash #-> {"foo" -> "bar"}
Ein elementweiser Vergleich von Hashtabellen ist mit der
Methode == möglich.
{1=>2, 3=>4} == {3=>4, 1=>2} #-> true
{1=>2, 3=>4} == {1=>2, 3=>5} #-> false
{1=>2, 3=>4} == {1=>2, 2=>4} #-> false
Ruby prüft, ob beide Hashes dieselben
Schlüssel beinhalten (selber Wert aller Schlüssel) und ob unter jedem
Schlüssel derselbe Wert (Gleichheit) gespeichert ist.
Die Methode invert erzeugt eine Hashtabelle, bei
der Schlüssel und Werte vertauscht sind.
h = {"a"=>1, "b"=>2} #-> {"a"=>1, "b"=>2}
h.invert #-> {1=>"a", 2=>"b"}
Falls zwei Werte gleich sind, so überschreibt Ruby stillschweigend beginnend von links.
{"a"=>1, "b"=>1}.invert #-> {1=>"b"}
Die Methoden keys und values dienen der Abfrage aller Schlüssel bzw.
aller Werte eines Hashes.
h = {"a"=>1, "b"=>2, "c"=>2}
h.keys #-> ["a", "b", "c"]
h.values #-> [1, 2, 2]
h.length #-> 3
h.size #-> 3
Für length gibt es wie immer die Alternative size.
Obwohl Hashtabellen ihre Elemente nicht anordnen, bietet
Ruby für sie eine Methode sort an. Allerdings ist das
Resultat ein (angeordnetes) Assoziationsarray, in dem die
Einträge nach den Schlüsselwerten sortiert sind.
{"b"=>2, "a"=>1, "c"=>3}.sort
#-> [["a", 1], ["b", 2], ["c", 3]]