efinf:blc2016:ruby:arrays

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).

# 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

Arrays können auch Arrays enthalten und damit können mehrdimensionale Arrays abgebildet werden:

multab = Array.new(5){|i| Array.new(5){|j| i*j}}
p multab
puts multab[3][2]

Zugriff

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

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. [[1],[1,1], [1,2,1], [1,3,3,1], etc.]

Lösungen

Lösungen

   # 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("")
   }
 

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| …}
  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(" ")}
 
  • efinf/blc2016/ruby/arrays.txt
  • Last modified: 2016/09/25 13:51
  • by Ivo Blöchliger