Über Listen - Theorie Lektion 5

Erstellt von Frithjof Thu, 02 Aug 2007 20:01:00 GMT

Diese Lektion und vielleicht noch eine weitere, dann fängst du aber wirklich an, ein Spiel in Ruby zu programmieren. Jetzt lernst du ein sehr wichtiges Dings. Das Dings gehört zu den sogenannten Datenstrukturen.

Du weißt bereits, wie man eine Zahl oder eine Zeichenkette in Ruby verwendet. Was aber, wenn du gleich mehrere Zahlen oder Zeichenketten als ein Ganzes verwenden möchtest, sozusagen eine Liste mit Zahlen oder Zeichenketten?

Einfache Liste in Ruby

Schau dir diesen Code an:


# theorie_05.rb

zahlen_liste = [2, 4, 6, 8, 10]

planeten_liste = [
  "Merkur",  "Venus", 
  "Erde",    "Mars", 
  "Jupiter", "Saturn", 
  "Uranus", "Neptun",
]

irgendwas_liste = ["Mars", 95, "95", 95, "Quark"]

leere_liste = []

Du siehst, eine Liste ist ganz einfach zu erstellen. Der Anfang einer Liste wird mit der öffnenden eckigen Klammer [ markiert, das Ende der Liste mit der schließenden eckigen Klammer ]. Zwischen die Klammern schreibst die Glieder der Liste und trennst sie jeweils mit einem Komma ab. Ein Komma darf auch nach dem letzten Glied in einer Liste stehen, aber nicht vor dem ersten. Man bezeichnet die Dinge in einer Liste als Mitglieder oder Elemente der Liste. Eine Liste ohne Elemente heißt die leere Liste.

Eine Liste kann aus einheitlichen Elementen bestehen, also bspw. nur Zahlen. Sie kann aber auch Elemente verschiedenen Typs enthalten, also bspw. Zeichenketten und Zahlen. Ein Element einer Liste kann sogar selbst wieder eine Liste sein!

Eine Liste kann mehrere identische Elemente enthalten. Bspw. in der irgendwas_liste ist die 95 zweimal enthalten. Oder dreimal? Nein, für Ruby ist das Element 95 eine Zahl, das Element "95" aber eine Zeichenkette. Daher ist die Zahl 95 nur zweimal enthalten.

Verteile die Elemente einer Liste über mehrere Zeilen, damit es besser lesbar ist, was in der Liste so alles enthalten ist. Du brauchst die Liste also nicht in eine einzige Zeile zu quetschen.

Listen nennt man auch Array (engl. für Anordung, Reihe) oder Vektor. Genaugenommen ist eine Liste etwas mehr als ein Array. Bei einer Liste kennt jedes Element ihre unmittelbaren Nachbarelemente, entweder das davor und das danach oder nur eines von beiden. Das was wir hier in diesem Artikel als Liste kennen lernen ist daher genaugenommen nur ein Array, weil die Elemente sich selbst untereinander nicht kennen. Wir bleiben aber hier trotzdem bei dem Begriff Liste, weil man eher begreift, was gemeint ist.

Ausgabe einer einfachen Liste

Angenommen wir definieren eine Einkaufsliste mit den Elementen Butter, Milch, Honig und Brot. Dann können wir die Liste natürlich einfach mit dem puts Befehl ausgeben. Dabei wird jedes Element der Liste in einer neuen Zeile ausgegeben.

Ruby bietet dir aber noch eine schönere Ausgabe der Liste an. Auf englisch heißt das pretty print (schöner Druck). Verwende statt puts den Befehl pp (dabei steht pp für pretty print). Bevor du diesen Befehl in deinem Programm verwenden kannst, muss du ihn im Programm bekannt machen über ein require ‘pp’ am Anfang der Datei:


require 'pp'

# Einzelne Einkaufslisten
tegut = ["Butter", "Milch", "Honig", "Brot"]
obi   = ["Schrauben", "Leimholz", "Kabel", "Lampe"]
dm    = ["Duschbad für Mama",    "Deo für Papa", 
         "Haarspange für Livia", "Zahnbürste für Peter"]

# Gesamte Einkaufsliste, enthält die einzelnen Listen
einkauf = [tegut, obi, dm]

# Normale Ausgabe
puts einkauf

# Schickere Ausgabe mit pretty print
pp einkauf

# Ausgabe des dritten Elementes der Liste
pp einkauf[2]

Du siehst hier auch, dass eine Liste als Elemente wiederum Listen enthalten kann. Die Liste obi mit ihren Elementen "Schrauben", "Leimholz", "Kabel", "Lampe" wird in der Liste einkauf als zweites Element gespeichert.

Die gesamte Liste auszugeben ist gut und schön. Häufiger jedoch möchtest du nur bestimmte Elemente der Liste ausgeben. Ruby nummeriert die Elemente durch, sodass du einfach nur die Nummer des Elementes angeben musst. Das machst du, indem du direkt an den Variablennamen der Liste die gewünschte Nummer in eckige Klammern anhängst.

Aber Achtung: Ruby beginnt beim Durchnummerieren der Elemente in einer Liste immer mit 0, nicht mit 1! Möchtest du das dritte Element in der Einkaufsliste einkauf ausgeben, musst du somit einkauf[2] schreiben, nicht einkauf[3], weil das erste Element in der Liste nämlich nicht einkauf[1], sondern einkauf[0] ist.

Hash – Liste mit Index

Ruby kennt noch eine weitere wichtige listenähnliche Datenstruktur. Es ist eigentlich eine Art Doppelliste bestehend aus zwei Listen: eine Liste mit Namen und eine Liste, die für jeden Namen den zugehörigen Wert enthält. Den Namen nennt man auch Schlüssel oder englisch Key oder Index. Ein bestimmter Key darf in dieser Liste nur höchstens einmal vorkommen. Daher heißt diese Datenstruktur auch Indextabelle oder englisch Hashtable oder einfach nur ein Hash. Verwende einen Hash immer dann, wenn du schnell über einen Schlüsselnamen auf einen zugehörigen Wert zugreifen möchtest.

Der folgende Hash legt für jeden Namen eines deutschen Zahlwortes oder einer natürlichen Zahl von 1 bis 10 als zugehörigen Wert das Zahlwort in spanischer Sprache ab.


require 'pp'

deutsch_spanisch = {
  1        => "uno",
  "eins"   => "uno",
  2        => "dos",
  "zwei"   => "dos",
  3        => "tres",
  "drei"   => "tres",
  4        => "cuatro",
  "vier"   => "cuatro",
  5        => "cinco", 
  "fuenf"  => "cinco", 
  6        => "seis",
  "sechs"  => "seis",
  7        => "siete",
  "sieben" => "siete",
  8        => "ocho",
  "acht"   => "ocho",
  9        => "nueve",
  "neun"   => "nueve",
  10       => "diez",
  "zehn"   => "diez",
}
pp deutsch_spanisch
puts "Vier heisst auf Spanisch #{deutsch_spanisch['vier']}." 
puts "Acht heisst auf Spanisch #{deutsch_spanisch[8]}." 

Ein Hash wird ähnlich einer Liste definiert aber mit folgenden Unterschieden. Der Anfang und das Ende des Hash werden mit geschweiften Klammern (anstatt eckiger) markiert. Die Elemente des Hash werden zwar auch mit Komma getrennt, aber ein Element besteht immer aus einem Name-Wert-Paar. Zuerst schreibst du den Namen hin (eine Zahl oder eine Zeichenkette, oder …), dann einen nach rechts gerichteten Pfeil => und auf die rechte Seite des Pfeils schreibst du den Wert. Lies den Pfeil als wenn du sprichst: dem Namen (oder Key) sowieso ordne ich den Wert soundso zu.

Du siehst in unserem deutsch_spanisch Hash auch, dass es zwar gleiche Werte auf der rechten Seite geben kann, auf der linken Seite darf jeder Key aber nur höchstens einmal vorkommen. Kommt ein Key aber trotzdem auf der linken Seite mehrmals vor, dann speichert Ruby nur den zuletzt genannten Wert im Hash ab.


require 'pp'

deutsch_spanisch = {
  "acht" => "ocho",
  "acht" => "otscho",
}
puts "Acht heisst auf Spanisch #{deutsch_spanisch['acht']}." 

Dieser Hash hat nur ein Element! Der Wert für den Key acht wird beim zweiten mal überschrieben und hat am Ende nur einen Wert otscho.

Durchgehen von Listen und Hashes

Nicht selten muss man eine Liste durchgehen und mit jedem Element der Liste etwas bestimmtes unternehmen. Oder man möchte für alle Keys in einem Hash die Werte untersuchen. Schauen wir uns zunächst an, wie man für eine Liste alle Elemente durchgeht:



# Schleife über eine Liste

planeten = [
  "Merkur",  "Venus", 
  "Erde",    "Mars", 
  "Jupiter", "Saturn", 
  "Uranus", "Neptun",
]

for planet in planeten
  # Nur die Planeten ausgeben, in deren Namen ein e vorkommt.
  if planet.include?("e")
    puts planet
  end
end

Das Durchgehen einer Liste nennt man auch einen Loop über eine Liste machen. Loop (englisch für Schleife) deswegen, weil man schleifenartig ein Element nach dem anderen abklappert. Die Schleife beginnt mit dem for planet in planeten und endet mit end. Am Beginn der Schleife wird der Variablen planet bei jedem Durchgang der Wert des jeweils nächsten Elements zugewiesen. Diese Variable ist nur innerhalb der Schleife bekannt. Man nennt sie daher auch Schleifenvariable. Wenn alle Elemente in der Schleife behandelt wurden, setzt Ruby das Programm nach dem end fort.

Für einen Hash könnte ein Schleifendurchgang etwa so aussehen.



# Schleife über einen Hash

de_esp = {
  "eins"   => "uno",
  "zwei"   => "dos",
  "drei"   => "tres",
  "vier"   => "cuatro",
  "fuenf"  => "cinco", 
  "sechs"  => "seis",
  "sieben" => "siete",
  "acht"   => "ocho",
  "neun"   => "nueve",
  "zehn"   => "diez",
}

for key in de_esp.keys
  if de_esp[key].include?("t")
    puts de_esp[key]
  end
end

Die Liste aller Keys für den Hash de_esp bekommen wir mit de_esp.keys. Diese Liste gehen wir durch und verwenden den jeweiligen Key dazu, uns den zugehörigen Wert aus dem Hash zu holen—hier das Zahlwort auf Spanisch. Enthält der Hashwert (das spanische Zahlwort) ein t im Namen, dann geben wir es mit puts aus.

Natürlich hat Ruby noch mehrer Möglichkeiten, Schleifen über Listen und Hashes zu machen. Aber die hier vorgestellte for-Schleife ist gut lesbar und fürs erste ausreichend.

Üben mit Peter und Livia

Livia: Schreibe die Einkaufsliste von oben als Hash um. Verwende dabei die Variablennamen der einzelnen Einkaufslisten (tegut, obi, dm) als Keys im Hash! Was fällt dir bei der pretty print Ausgabe bezüglich der Reihenfolgen von Liste und Hash auf?

Peter: Zähle bitte auf, wozu man alles die eckigen Klammern [ ] bei Listen und Hashes benutzt!

Trackbacks

Verwenden Sie den folgenden Link zur Rückverlinkung von Ihrer eigenen Seite:
http://www.rubykids.de/trackbacks?month=08&year=2007&article_id=listen&day=02

Meine Nachricht

Einen Kommentar hinterlassen

Comments