Programmierung in Ruby

Der Leitfaden der Pragmatischen Programmierer

module Enumerable
Relies on: each, <=>

Index:

collect detect each_with_index entries find find_all grep include? map max member? min reject select sort to_a


Das Enumerable-Mixin stellt Auflistungs-Klassen mit verschiedenen Traversierungs- und Such-Methoden zur Verfügung, sowie die Möglichkeit der Sortierung. Die Klasse muss eine each-Methode unterstützen, die nacheinander für alle Mitglieder der Auflistung Yield aufruft. Falls Enumerable#max, #min oder #sort benutzt wird, müssen die Objekte in der Auflistung außerdem einen sinnvollen <=>-Operator unterstützen, da diese Methoden auf einer Anordnung zwischen Mitgliedern der Auflistung beruhen.

instance methods
collect enumObj.collect {| obj | block }

-> anArray

Liefert ein neues Array mit den jeweiligen Ergebnissen der Ausführung von block für jedes Element in enumObj.

(1..4).collect {|i| i*i } » [1, 4, 9, 16]
(1..4).collect { "cat"  } » ["cat", "cat", "cat", "cat"]

detect enumObj.detect {| obj | block }

-> anObject or nil

Übergibt jeden Eintrag in enumObj an block. Liefert den ersten, bei dem block nicht false ist. Liefert nil, falls kein passendes Objekt gefunden wurde.

(1..10).detect  {|i| i % 5 == 0 and i % 7 == 0 } » nil
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } » 35

each_with_index enumObj.each_with_index {| obj, i | block }

-> nil

Ruft block mit zwei Argumenten auf, dem Item (Eintrag) und seinem Index, für jedes Item in enumObj.

hash = Hash.new
%w(cat dog wombat).each_with_index {|item, index|
  hash[item] = index
}
hash » {"dog"=>1, "wombat"=>2, "cat"=>0}

entries enumObj.entries -> anArray

Synonym für Enumerable#to_a.

find enumObj.find {| obj | block }

-> anObject or nil

Synonym für Enumerable#detect.

find_all enumObj.find_all {| obj | block }

-> anArray

Liefert ein Array mit allen Elementen von enumObj, für die block nicht false ist (siehe auch Enumerable#reject).

(1..10).find_all {|i|  i % 3 == 0 } » [3, 6, 9]

grep enumObj.grep( pattern ) -> anArray
enumObj.grep( pattern ) {| obj | block }-> anArray

Liefert ein Array mit allen Elementen in enumObj, für die Pattern === element. Falls der optionale block angegeben ist, wird jedes gefundene Element an ihn übergeben und die Ergebnisse des Blocks werden ins Array geschrieben.

(1..100).grep 38..44 » [38, 39, 40, 41, 42, 43, 44]
c = IO.constants
c.grep(/SEEK/) » ["SEEK_END", "SEEK_CUR", "SEEK_SET"]
res = c.grep(/SEEK/) {|v| IO.const_get(v) }
res » [2, 1, 0]

include? enumObj.include?( anObject ) -> true or false

Liefert true, falls irgendein Mitglied von enumObj gleich anObject ist. Gleichheit wird mit == geprüft.

IO.constants.include? "SEEK_SET" » true
IO.constants.include? "SEEK_NO_FURTHER" » false

map enumObj.map {| obj | block }

-> anArray

Synonym für Enumerable#collect.

max enumObj.max -> anObject
enumObj.max {| a,b | block }-> anObject

Liefert das Objekt in enumObj mit dem maximalen Wert. Bei der ersten Form wird angenommen, dass alle Objekte Comparable implementiert haben; bei der zweiten wird der Block benutzt, um a <=> b zurückzuliefern.

a = %w(albatross dog horse)
a.max » "horse"
a.max {|a,b| a.length <=> b.length } » "albatross"

member? enumObj.member?( anObject ) -> true or false

Synonym für Enumerable#include?.

min enumObj.min -> anObject
enumObj.min {| a,b | block }-> anObject

Liefert das Objekt in enumObj mit dem minimalen Wert. Bei der ersten Form wird angenommen, dass alle Objekte Comparable implementiert haben; bei der zweiten wird der Block benutzt, um a <=> b zurückzuliefern.

a = %w(albatross dog horse)
a.min » "albatross"
a.min {|a,b| a.length <=> b.length } » "dog"

reject enumObj.reject {| obj | block }

-> anArray

Liefert ein Array mit allen Elementen von enumObj, für die block false ist (siehe auch Enumerable#find_all).

(1..10).reject {|i|  i % 3 == 0 } » [1, 2, 4, 5, 7, 8, 10]

select enumObj.select {| obj | block }

-> anArray

Synonym für Enumerable#find_all.

sort enumObj.sort -> anArray
enumObj.sort {| a, b | block }-> anArray

Liefert ein Array mit den Items aus enumObj in sortierter Reihenfolge, entweder nach ihrer eigenen <=>-Methode oder über die Ergebnisse des angegebenen Blocks. Der Block sollte -1, 0 oder +1 zurückliefern, je nach dem Ergebnis des Vergleichs zwischen a und b.

%w(rhea kea flea).sort » ["flea", "kea", "rhea"]
(1..10).sort {|a,b| b <=> a} » [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Der folgende Code sortiert ein paar Dateien nach ihrem Modifikations-Datum.

files = Dir["*"]
sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
sorted » ["mon", "tues", "wed", "thurs"]

Diese Sortierung ist ineffizient: sie erzeugt zwei neue File-Objekte während jedes Vergleichs. Etwas besser ist es, die Kernel#test-Methode zum Generieren der Modifikations-Datums direkt zu benutzen.

files = Dir["*"]
sorted = files.sort { |a,b|
  test(?M, a) <=> test(?M, b)
}
sorted » ["mon", "tues", "wed", "thurs"]

Dabei werden immer noch viele unnötige Time-Objekte erzeugt. Eine effizientere Technik ist es, die Sortierungs-Schlüssel (in diesem Fall die Modifikations-Datums) vor der Sortierung zu speichern. Perl-Benutzer nennen diese Vorgehensweise oft eine Schwartzian-Transformation, nach Randal Schwartz. Wir konstruieren uns ein Array, bei dem jedes Element ein Array mit dem Sortierungs-Schlüssel sowie dem Dateinamen ist. Wir sortieren dieses Array und holen dann die Dateinamen aus diesem Ergebnis.

sorted = Dir["*"].collect { |f|
   [test(?M, f), f]
}.sort.collect { |f| f[1] }
sorted » ["mon", "tues", "wed", "thurs"]

to_a enumObj.to_a -> anArray

Liefert ein Array mit allen Items aus enumObj.

(1..7).to_a » [1, 2, 3, 4, 5, 6, 7]
{ 'a'=>1, 'b'=>2, 'c'=>3 }.to_a » [["a", 1], ["b", 2], ["c", 3]]


Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Übersetzung: Jürgen Katins
Für das englische Original:
© 2000 Addison Wesley Longman, Inc. Released under the terms of the Open Publication License V1.0. That reference is available for download.
Diese Lizenz sowie das Original vom Herbst 2001 bilden die Grundlage der Übersetzung
Es wird darauf hingewiesen, dass sich die Lizenz des englischen Originals inzwischen geändert hat.
Für die deutsche Übersetzung:
© 2002 Jürgen Katins
Der Copyright-Eigner stellt folgende Lizenzen zur Verfügung:
Nicht-freie Lizenz:
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/). Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.
Freie Lizenz:
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".