Ruby-Programmierung: Hashes

Zurück zum Inhaltsverzeichnis.

Hashes sind den vorher besprochenen Arrays sehr ähnlich. Sie dienen ebenfalls dazu auf verschiedene Daten strukturiert zugreifen zu können. Unterschiede zeigen sich in Ordnung und Indizierung. Die Ordnung eines Hashes entsteht durch die Reihenfolge des Hinzufügens, während es bei einem Array kein Problem ist das vierte vor dem dritten Element einzufügen. Arrays werden außerdem über Zahlen Indiziert, Hashes über beliebige Objekte. Das ist insbesondere von Vorteil, wenn die Daten nicht gleichwertig in ihrer Bedeutung sind.

Erzeugen und Zugriff

Bearbeiten

Die häufigste Benutzung von Hashes ist die Indizierung mit Symbolen. Die Syntax ist denen von Arrays sehr ähnlich, lediglich die Erstellung mit Werten unterscheidet sich deutlich, da man gleichzeitig Index und Wert angeben muss. Das folgende Beispiel verdeutlicht den Nutzen der Indizierung mit Symbolen.

person = {}
person2 = {:name => "Klaus Müller", :age => 21 }
person[:name] = "Hans Schuster"
person[:age] = 20
puts "#{ person[:name] } ist #{ person[:age] } Jahre alt."

In Anlehnung an die Schreibweise von JSON gibt es in Ruby auch die Möglichkeit einen Hash mit Symbolen so zu erzeugen: person2 = { name: "Klaus Müller", age: 21 }, das ist zu der oben dargestellten Schreibweise äuqivalent. Falls Sie jedoch andere Objekte als Index verwenden müssen Sie dies wie oben gezeigt tun, z.B. ages = { "Klaus Müller" => 21, "Hans Schuster" => 20 }

Ein Element des Hash' bezeichnet man als Key-Value-Paar. Implementiert man die gleiche Funktionalität mit einem Array, dann würde der Zugriff wohl über person[0] und person[1] erfolgen, das ist nicht nur sehr viel schlechter lesbar, es hat auch den Nachteil deutlich weniger flexibel zu sein. Möchte man später neben Namen und Alter auch noch den Geburtsnamen speichern, dann müsste man entweder sich merken, dass der Name an Stelle 0 und der Geburtsname an der Stelle 2 gespeichert ist, oder alles um eins verschieben, wodurch jedoch der sämtliche Programmcode angepasst werden muss. Bei Hashes fügt man einen neuen Index an und der restliche Code bleibt unberührt.

Rückblick: Kassenbon

Bearbeiten

Das Kassenbonprogramm aus dem letzten Kapitel hatte einen großen Nachteil: eine Produktangabe fehlte. Mit einem Hash sind wir in der Lage dieses Manko zu beseitigen.

# kasse.rb
 
# Endlosschleife erzeugen
loop do
  puts "Neuer Bon:"  
 
  #Kassenbon anlegen
  prices = {}
  product = ""
  price = ""
  #Preiseingabe beenden durch leeres Produkt
  until product == "\n"
    print "Produkt:\t"
    product = gets
    print "Preis:\t"
    price = gets.to_f
    prices[product.chomp] = price unless product == "\n"
  end
 
  #Summe errechnen und Bon ausgeben
  puts "Ihr Einkauf:"
  sum = 0.0
  for name, price in prices
    sum += price
    puts "#{ name }:\t#{ price } EUR"
  end
 
  #Wenn der Kassenbon leer war, Programm beenden
  puts "Ihr Einkauf kostet:\t#{ sum } EUR" unless sum == 0.0
  break if sum == 0.0
end

Das Programm erwartet die abwechselnde Eingabe von Produktnamen und -preis und wird ähnlich wie im vorhergehenden Beispiel durch leere Eingaben beendet.

  • Zeile 17 .chomp ist eine Methode die aus einem String das letzte Zeichen entfernt, in diesem Fall ist es das Newlinezeichen \n. Dies erfolgt, damit der Bon korrekt ausgeben wird.

Eine weitere ähnliche Form der Aufbereitung von Daten sind Sets. Sie füllen gewissermaßen eine Lücke zwischen Hashes und Arrays. Sets sind ungeordnet wie Hashes und ermöglichen überhaupt keinen Zugriff auf ein einzelnes Element. Sie sind dabei einer Menge im mathematischen Sinne am ähnlichsten.

require 'set'
s = Set.new
s << 1
s << 2
s.inspect
s << 2
s.inspect

Die Funktion .inspect ist eine spezielle Methode, die auf allen Standardobjekten definiert ist. Die einzelne Funktionalität kann dabei variieren, sie soll jedoch detaillierte Informationen über das vorhergehende Objekt ausgeben. In diesem Fall wird ausgegeben, dass es sich um ein Set handelt und welche Elemente es enthält.