efinf:blc2016:ruby:arrays

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

efinf:blc2016:ruby:arrays [2016/09/25 11:48] – created Ivo Blöchligerefinf:blc2016:ruby:arrays [2016/09/25 11:51] (current) – [Initialisierung] Ivo Blöchliger
Line 1: Line 1:
 +{{backlinks>.}}
 +
 +===== Array =====
 +Ein Array ist eine "Liste" von einer bestimmten Anzahl $n$ "Werten", die von 0 bis $n-1$ indiziert sind. Zugriff erfolgt in vielen Programmiersprachen mit eckigen Klammern, z.B. name[0], name[1], etc., wobei name der Variablenname ist.
 +
 +In vielen Programmiersprachen müssen alle Werte im Array den gleichen Typ haben und die Anzahl der Einträge muss am Anfang festgelegt werden und kann danach nicht mehr verändert werden.
 +
 +In Ruby gelten diese Einschränkungen nicht. Arrays sind extrem flexibel und konfortabel zu benutzen. Der Preis dafür ist eine langsamere Ausführung des Codes. Je nach Art der Array-Manipulation kann der Zeitaufwand schon mal proportional zur Anzahl der Elemente im Array sein (z.B. ein Element löschen oder einfügen).
 +
 +==== Initialisierung ====
 +<code ruby>
 +# leeres Array
 +a = []
 +a = Array.new
 +
 +# Array mit Einträgen
 +a = [4,"6",8.653]
 +puts a[0]  # liefert 4
 +p a    # Gleicher Effekt wie puts a.inspect
 +
 +a =%w(das ist ein Array mit Strings)  # Quote words
 +p a
 +
 +# Array mit konstantem Wert (Achtung bei Werten, die nicht Zahlen sind)
 +a = Array.new(10, 2)
 +p a
 +a[2]=3
 +p a
 +# Und hier das Problem
 +a = Array.new(10,"wtf")
 +a[2] = "lol"
 +p a
 +a[1][0..2]="lol"
 +p a
 +
 +# Array aus Bereich (Range) erzeugen:
 +a = (10..20).to_a
 +p a
 +
 +
 +# Array mit programmatisch erzeugten Inhalten
 +a = Array.new(10){"wtf"}
 +p a
 +a[1][0..2]="lol"
 +p a
 +
 +a = Array.new(10){|i| i*i}
 +p a
 +</code>
 +
 +Arrays können auch Arrays enthalten und damit können mehrdimensionale Arrays abgebildet werden:
 +
 +<code ruby>
 +multab = Array.new(5){|i| Array.new(5){|j| i*j}}
 +p multab
 +puts multab[3][2]
 +</code>
 +
 +=== Zugriff ===
 +<code ruby>
 +a = Array.new(10){|i| 100+i*i}
 +p a
 +puts "a[5]=#{a[5]}, a[2..4]=#{a[2..4].inspect} a[-1]=#{a[-1]}, a[-2]=#{a[-2]}"
 +a[2..4] = [2,3,4]
 +p a
 +a.push(1001)
 +p a
 +puts a.size
 +a[15]=200
 +p a
 +puts a.size
 +</code>
 +
 +==== Aufgaben ====
 +Erzeugen Sie ein Array einer gegebenen Länge mit
 +  * ungeraden Zahlen 1,3,5, etc.
 +  * allen ASCII-Symbolen von 32 bis 126
 +  * 1000 Würfelzahlen (Hinweis: rand(x) liefert ganzzahlen zwischen 0 und x-1 inklusive).
 +  * den Fibbonacci-Zahlen: 0,1,1,2,3,5,8,13,21,34, etc.
 +  * den Zeilen des Pascal-Dreiecks, d.h. <nowiki>[[1],[1,1], [1,2,1], [1,3,3,1], etc.]</nowiki>
 +
 +<hidden Lösungen>
 +<code ruby>
 +   # Ungerade Zahlen:
 +   # Effizient
 +   a=Array.new(42){|i| 2*i+1}
 +   # Ineffizient
 +   a = []
 +   42.times{|i| a[i]=2*i+1}
 +   
 +   # ASCII-Zeichen, ineffizient
 +   a = []
 +   32.upto(126){|i| a[i-32] = i.chr}
 +   # ASCII-Zeichen, effizient
 +   ((32.chr)..(126.chr)).to_a
 +   
 +   # Würfelzahlen
 +   a = Array.new(1000){rand(6)+1}
 +   
 +   # Fibbonacci Zahlen
 +   # Elegant, ineffizient weil Array dynamisch wächst
 +   a = [0,1]
 +   42.times{a.push(a[-1]+a[-2])
 +   # Explizite Formel, Konstanten vorberechnet für Effizienz, Ungenau ab ca. 16 Stellen.
 +   sq5 = Math.sqrt(5.0)
 +   phi = (1.0+sq5)/2.0;
 +   a = Array.new(42){|i| (phi**i/sq5+0.5).to_i}
 +   
 +   # Pascal-Dreieck
 +   a = [[1]]
 +   # Dieser Loop könnte auch auf einer Zeile ohne die Variable temp geschrieben werden.
 +   # Es ist aber wohl klarer, was abgeht.
 +   10.times{
 +      temp = Array.new(a.size-1){|i| a[-1][i]+a[-1][i+1]}
 +      a.push([1]+temp+[1])
 +   }
 +   # Nette Ausgabe (Zeilenumbrüche sind hier nur zur Lesbarkeit und könnten weggelassen werden)
 +   puts a.map.with_index{|linie, zeile| 
 +        " "*(((a.size-zeile-1))*4)+
 +        linie.map{|zahl| 
 +             sprintf("%8d",zahl)
 +        }.join("")
 +   }
 + 
 +</code>
 +</hidden>
 +==== Array Methoden ====
 +Umfangreiche Übersicht: https://www.tutorialspoint.com/ruby/ruby_arrays.htm
 +
 +=== Loops ===
 +  * .each{|e| ...}
 +  * .each_with_index{|e,i| ...}
 +
 +=== Manipulation ===
 +  * .map{|e| ...}  # Neues Array mit den Resultaten
 +  * .map!{|e| ...}  # Array wird überschrieben
 +  * .select{|e| ...} # Neues Array mit jenen Elementen, für die der Block {...} true ergibt
 +  * .join(" " # Elemente in String verwandeln (mit to_s) und Resultate durch " " getrennt zusammenfügen
 +  * .sort  # Neues Array, sortiert (Vergleiche mit <=>)
 +  * .sort! # Array wird verändert
 +  * .sort! {|a,b| ...Wert <0 wenn a<b, >0 wenn a>0, 0 sonst...}  # Sortierung mit eigener Sortierfunktion
 +  * .inject(startwert){|akkumulator, element| ...}
 +<code ruby>
 +  a = Array.new(100){rand(6)+1}
 +  durchschnitt = a.inject(0){|s,i| s+i}.to_f/a.size
 +  
 +  a = ["Cleve Blatter", "Dany Acker", "Anne Excuse", "Elton Cash", "Bobby Dash"]
 +  a.sort   # Alphabetisch, also nach Vornamen
 +  a.sort{|a,b| a.split(" ")[1]<=>b.split(" ")[1]}  # Alphabetisch, nach Nachnamen
 +  a.map{|e| e.split(" ")[0]}  # Vornamen
 +  a.map{|e| temp=e.split(" "); temp[0]=temp[0][0]+"."; temp.join(" ")}
 +  
 +</code>