Die Programmiersprache Ruby (German Edition)
"each_char liefert: #{x.inspect}"}
.to_a .tap {|x| puts "to_a liefert: #{x.inspect}"}
.map {|c| c.succ } .tap {|x| puts "map liefert: #{x.inspect}" }
.sort .tap {|x| puts "sort liefert: #{x.inspect}"}
Eine weitere gängige Funktion für Iteratoren ist die automatische Ressourcen-Deallokation. Die Methode
File.open
kann beispielsweise als Iterator verwendet werden. Sie öffnet die angegebene Datei und erzeugt dabei ein
File
-Objekt, um sie zu repräsentieren. Wenn kein Block mit dem Aufruf verknüpft ist, gibt sie einfach das
File
-Objekt zurück und überlässt dem aufrufenden Code die Verantwortung zum Schließen der Datei. Ist dagegen ein Block mit dem
File.open
-Aufruf verknüpft, wird das neue
File
-Objekt an diesen Block übergeben, und die Datei wird automatisch geschlossen, wenn der Block zurückkehrt. Das stellt sicher, dass Dateien stets geschlossen werden, und befreit Programmierer von diesem Wartungsdetail. In diesem Fall, wenn also ein Block mit dem Aufruf von
File.open
verknüpft ist, ist der Rückgabewert der Methode kein
File
-Objekt, sondern der Rückgabewert des Blocks.
----
Die Klasse
Integer
definiert drei häufig genutzte Iteratoren. Die Methode
upto
ruft ihren zugehörigen Block einmal für jeden Integer auf, der zwischen dem Integer, für den sie aufgerufen wird, und dem Integer, der als Argument übergeben wird, liegt, zum Beispiel:
4.upto(6) {|x| print x} # => Gibt "456" aus
Wie Sie sehen, übergibt
upto
jeden Integer an den verknüpften Block und fügt sowohl den Anfangs- als auch den Endwert in die Iteration ein. Im Allgemeinen führt
n.upto(m)
seinen Block
m-n+1
-mal aus.
Die Methode
downto
ist genau wie
upto
, iteriert aber von einer größeren Zahl nach unten zu einer kleineren.
Wenn die Methode
Integer.times
für den Integer
n
aufgerufen wird, ruft sie ihren Block
n
-mal auf und übergibt ihm in den aufeinanderfolgenden Iterationen die Werte
0
bis
n-1
, zum Beispiel:
3.times {|x| print x } # => Gibt "012" aus
Am Allgemeinen ist
n.times
äquivalent zu
0.upto(n-1)
.
Wenn Sie eine numerische Iteration mit Fließkommawerten durchführen möchten, können Sie das mithilfe der komplexeren, von der Klasse
Numeric
definierten Methode
step
tun. Der folgende Iterator beginnt beispielsweise bei
0
und iteriert in Schritten von
0.1
, bis er
Math::PI
erreicht:
0.step(Math::PI, 0.1) {|x| puts Math.sin(x) }
5.3.2 Enumerable-Objekte
Array
,
Hash
,
Range
und eine Reihe anderer Klassen definieren einen
each
-Iterator, der jedes Element der Sammlung an den verknüpften Block übergibt. Das ist möglicherweise der am häufigsten genutzte Iterator in Ruby; wie wir weiter oben gesehen haben, funktioniert die
for
-Schleife nur, wenn sie über Objekte iteriert, die
each
-Methoden haben. Hier sehen Sie Beispiele für
each
-Iteratoren:
[1,2,3].each {|x| print x } # => Gibt "123" aus
(1..3).each {|x| print x } # => Gibt "123" aus; dasselbe wie 1.upto(3)
Den Iterator
each
gibt es nicht nur für traditionelle »Datenstruktur«-Klassen. Rubys IO-Klasse definiert einen
each
-Iterator, der die aus dem Ein-/Ausgabeobjekt gelesenen Textzeilen verarbeitet. Auf diese Weise können Sie die Zeilen einer Datei in Ruby mit Code wie diesem verarbeiten:
File.open(filename) do |f| # Benannte Datei öffnen, als f übergeben
f.each {|line| print line } # Jede Zeile in f ausgeben
end # Block beenden und Datei schließen
Die meisten Klassen, die eine
each
-Methode definieren, importieren auch das Modul
Enumerable
; es definiert eine Reihe speziellerer Iteratoren, deren Implementierung auf die Methode
each
aufbaut. Ein solcher nützlicher Iterator ist
each_with_index
, der es uns ermöglicht, eine Zeilennummerierung zu dem vorigen Beispiel hinzuzufügen:
File.open(filename) do |f|
f.each_with_index do |line,number|
print "#{number}: #{line}"
end
end
Einige der am häufigsten eingesetzten
Enumerable
-Iteratoren sind die Methoden
collect
,
select
,
reject
und
inject
, deren Namen sich reimen. Die Methode
collect
(auch als
map
bekannt) führt den mit ihr verknüpften Block für jedes Element des Aufzählungsobjekts aus und sammelt die Rückgabewerte des Blocks in einem Array:
squares = [1,2,3].collect {|x| x*x} # => [1,4,9]
Die Methode
select
ruft den zugehörigen Block für jedes Element im Aufzählungsobjekt auf und gibt ein Array von Elementen zurück, für die der Block einen anderen Wert als
false
oder
nil
zurückgibt, zum Beispiel:
evens = (1..10).select {|x| x%2 == 0} # => [2,4,6,8,10]
Die Methode
reject
ist
Weitere Kostenlose Bücher