Programming Ruby

The Pragmatic Programmer's Guide

Previous < Contents ^
Next >

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


The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to sort. The class must provide a method each, which yields successive members of the collection. If Enumerable#max , #min, or #sort is used, the objects in the collection must also implement a meaningful <=> operator, as these methods rely on an ordering between members of the collection.

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

-> anArray

Returns a new array with the results of running block once for every 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

Passes each entry in enumObj to block. Returns the first for which block is not false. Returns nil if no object matches.

(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

Calls block with two arguments, the item and its index, for each item in enumObj.

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

entries enumObj.entries -> anArray

Synonym for Enumerable#to_a .

find enumObj.find {| obj | block }

-> anObject or nil

Synonym for Enumerable#detect .

find_all enumObj.find_all {| obj | block }

-> anArray

Returns an array containing all elements of enumObj for which block is not false (see also Enumerable#reject ).

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

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

Returns an array of every element in enumObj for which Pattern === element. If the optional block is supplied, each matching element is passed to it, and the block's result is stored in the output array.

(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

Returns true if any member of enumObj equals anObject. Equality is tested using ==.

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

map enumObj.map {| obj | block }

-> anArray

Synonym for Enumerable#collect .

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

Returns the object in enumObj with the maximum value. The first form assumes all objects implement Comparable; the second uses the block to return a <=> b.

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 for Enumerable#include? .

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

Returns the object in enumObj with the minimum value. The first form assumes all objects implement Comparable; the second uses the block to return a <=> b.

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

reject enumObj.reject {| obj | block }

-> anArray

Returns an array for all elements of enumObj for which block is false (see also Enumerable#find_all ).

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

select enumObj.select {| obj | block }

-> anArray

Synonym for Enumerable#find_all .

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

Returns an array containing the items in enumObj sorted, either according to their own <=> method, or by using the results of the supplied block. The block should return -1, 0, or +1 depending on the comparison between a and 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]

The following code sorts some files on modification time.

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

This sort is inefficient: it generates two new File objects during every comparison. A slightly better technique is to use the Kernel#test method to generate the modification times directly.

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

This still generates many unnecessary Time objects. A more efficient technique is to cache the sort keys (modification times in this case) before the sort. Perl users often call this approach a Schwartzian Transform, after Randal Schwartz. We construct a temporary array, where each element is an array containing our sort key along with the filename. We sort this array, and then extract the filename from the result.

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

to_a enumObj.to_a -> anArray

Returns an array containing the items in 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]]


Previous < Contents ^
Next >

Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright © 2001 by Addison Wesley Longman, Inc. 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.