module Enumerable(T)

Overview

The Enumerable mixin provides collection classes with several traversal, searching, filtering and querying methods.

Including types must provide an #each method, which yields successive members of the collection.

For example:

class Three
  include Enumerable(Int32)

  def each
    yield 1
    yield 2
    yield 3
  end
end

three = Three.new
three.to_a                      #=> [1, 2, 3]
three.select &.odd?             #=> [1, 3]
three.all? { |x| x < 10 }       #=> true

Note that most search and filter methods traverse an Enumerable eagerly, producing an Array as the result. For a lazy alternative refer to the Iterator and Iterable modules.

Direct including types

Array(T), BitArray, CharReader, Dir, Iterator(T), Matrix(T), Range(B, E), Set(T), Slice(T), StaticArray(T, N), Tuple(T*), XML::Attributes, XML::NodeSet

Defined in:

Instance Method Summary

Instance Method Detail

def all?

Returns true if none of the elements of the collection is false or nil.

[nil, true, 99].all?  #=> false
[15].all?             #=> true

def all?(&block)

Returns true if the passed block returns a value other than false or nil for all elements of the collection.

["ant", "bear", "cat"].all? { |word| word.length >= 3 }  #=> true
["ant", "bear", "cat"].all? { |word| word.length >= 4 }  #=> false

def any?

Returns true if at least one of the collection members is not false or nil.

[nil, true, 99].any?  #=> true
[nil, false].any?     #=> false

def any?(&block)

Returns true if the passed block returns a value other than false or nil for at least one element of the collection.

["ant", "bear", "cat"].any? { |word| word.length >= 4 }  #=> true
["ant", "bear", "cat"].any? { |word| word.length > 4 }   #=> false

def compact_map(&block)

Returns an array with the results of running the block against each element of the collection, removing nil values.

["Alice", "Bob"].map { |name| name.match(/^A./) }         #=> [#<MatchData "Al">, nil]
["Alice", "Bob"].compact_map { |name| name.match(/^A./) } #=> [#<MatchData "Al">]

def count(item)

Returns the number of times that the passed item is present in the collection.

[1, 2, 3, 4].count(3)  #=> 1

def count

Returns the number of elements in the collection.

[1, 2, 3, 4].count  #=> 4

def count(&block)

Returns the number of elements in the collection for which the passed block returns true.

[1, 2, 3, 4].count { |i| i % 2 == 0 }  #=> 2

def cycle(&block)

Calls the given block for each element in this enumerable forever.


def cycle(n, &block)

Calls the given block for each element in this enumerable n times.


abstract def each(&block : T -> _)

Must yield this collection's elements to the block.


def each_cons(count : Int, &block)

Iterates over the collection yielding chunks of size count, but advancing one by one.

[1, 2, 3, 4, 5].each_cons(2) do |cons|
  puts cons
end

Prints:

[1, 2]
[2, 3]
[3, 4]
[4, 5]

def each_slice(count : Int, &block)

Iterates over the collection in slices of size count, and runs the block for each of those.

[1, 2, 3, 4, 5].each_slice(2) do |slice|
  puts slice
end

Prints:

[1, 2]
[3, 4]
[5]

Note that the last one can be smaller.


def each_with_index(offset = 0, &block)

Iterates over the collection, yielding both the elements and their index.

["Alice", "Bob"].each_with_index do |user, i|
  puts "User ##{i}: #{user}"
end

Prints:

User #0: Alice
User #1: Bob

Accepts an optional offset parameter, which tells it to start counting from there. So, a more humand friendly version of the previous snippet would be:

["Alice", "Bob"].each_with_index(1) do |user, i|
  puts "User ##{i}: #{user}"
end

Which would print:

User #1: Alice
User #2: Bob

def each_with_object(obj, &block)

Iterates over the collection, passing each element and the initial object obj. Returns that object.

["Alice", "Bob"].each_with_object({} of String => Int32) do |user, lengths|
  lengths[user] = user.length
end  #=> {"Alice" => 5, "Bob" => 3}

def find(if_none = nil, &block)

Returns the first element in the collection for which the passed block is true.

Accepts an optional parameter if_none, to set what gets returned if no element is found (defaults to nil).

[1, 2, 3, 4].find { |i| i > 2 }      #=> 3
[1, 2, 3, 4].find { |i| i > 8 }      #=> nil
[1, 2, 3, 4].find(-1) { |i| i > 8 }  #=> -1

def first(count : Int)

Returns an array with the first count elements in the collection.

If count is bigger than the number of elements in the collection, returns as many as possible. This include the case of calling it over an empty collection, in which case it returns an empty array (unlike the variant without a parameter).


def first

Returns the first element in the collection. Raises EmptyEnumerable if the collection is empty.


def first?

Returns the first element in the collection. When the collection is empty, returns nil.


def flat_map(&block : T -> Array(U))

Returns a new array with the concatenated results of running the block (which is expected to return arrays) once for every element in the collection.

["Alice", "Bob"].flat_map do |user|
  user.chars
end  #=> ['A', 'l', 'i', 'c', 'e', 'B', 'o', 'b']

def grep(pattern)

Returns an array with all the elements in the collection that match the RegExp pattern.

["Alice", "Bob"].grep(/^A/)  #=> ["Alice"]

def group_by(&block : T -> U)

Returns a Hash whose keys are each different value that the passed block returned when run for each element in the collection, and which values are an array of the elements for which the block returned that value.

["Alice", "Bob", "Ary"].group_by { |name| name.length }  #=> {5 => ["Alice"], 3 => ["Bob", "Ary"]}

def in_groups_of(size : Int, filled_up_with = nil)

Returns an Array with chunks in the given size, eventually filled up with given value or nil.

[1, 2, 3].in_groups_of(2, 0) #=> [[1, 2], [3, 0]]
[1, 2, 3].in_groups_of(2) #=> [[1, 2], [3, nil]]

def in_groups_of(size : Int, filled_up_with = nil, &block)

Yields a block with the chunks in the given size.

[1, 2, 4].in_groups_of(2, 0) { |e| p e.sum }
#=> 3
#=> 4

def includes?(obj)

Returns true if the collection contains obj, false otherwise.

[1, 2, 3].includes?(2)  #=> true
[1, 2, 3].includes?(5)  #=> false

def index(&block)

Returns the index of the first element for which the passed block returns true.

["Alice", "Bob"].index { |name| name.length < 4 }  #=> 1 (Bob's index)

Returns nil if the block didn't return truefor any element.


def index(obj)

Returns the index of the object obj in the collection.

["Alice", "Bob"].index("Alice")  #=> 0

Returns nil if obj is not in the collection.


def index_by(&block : T -> U)

def inject(memo, &block)

Just like the other variant, but you can set the initial value of the accumulator.

[1, 2, 3, 4, 5].inject(10) { |acc, i| acc + i }  #=> 25

def inject(&block)

Combines all elements in the collection by applying a binary operation, specified by a block.

For each element in the collection the block is passed an accumulator value (memo) and the element. The result becomes the new value for memo. At the end of the iteration, the final value of memo is the return value for the method. The initial value for the accumulator is the first element in the collection.

[1, 2, 3, 4, 5].inject { |acc, i| acc + i }  #=> 15

def join(separator = "")

Returns a String created by concatenating the elements in the collection, separated by separator (defaults to none).

[1, 2, 3, 4, 5].join(", ")  #=> "1, 2, 3, 4, 5"

def join(separator = "", &block)

Returns a String created by concatenating the results of passing the elements in the collection to the passed block, separated by separator (defaults to none).

[1, 2, 3, 4, 5].join(", ") { |i| -i }  #=> "-1, -2, -3, -4, -5"

def join(separator, io, &block)

Prints to io the concatenation of the elements, with the possibility of controlling how the printing is done via a block.

[1, 2, 3, 4, 5].join(", ", STDOUT) { |i, io| io << "(#{i})" }

Prints:

(1), (2), (3), (4), (5)

def join(separator, io)

Prints to io all the elements in the collection, separated by separator.

[1, 2, 3, 4, 5].join(", ", STDOUT)

Prints:

1, 2, 3, 4, 5

def map(&block : T -> U)

Returns an array with the results of running the block against each element of the collection.

[1, 2, 3].map { |i| i * 10 }  #=> [10, 20, 30]

def map_with_index(&block : T, Int32 -> U)

Like #map, but the block gets passed both the element and its index.

["Alice", "Bob"].map_with_index { |name, i| "User ##{i}: #{name}" }  #=> ["User #0: Alice", "User #1: Bob"]

def max

Returns the element with the maximum value in the collection.

It compares using > so it will work for any type that supports that method.

[1, 2, 3].max         #=> 3
["Alice", "Bob"].max  #=> "Bob"

Raises EmptyEnumerable if the collection is empty.


def max_by(&block : T -> U)

Returns the element for which the passed block returns with the maximum value.

It compares using > so the block must return a type that supports that method

["Alice", "Bob"].max_by { |name| name.length }  #=> "Alice"

Raises EmptyEnumerable if the collection is empty.


def max_of(&block : T -> U)

Like #max_by but instead of the element, returns the value returned by the block.

["Alice", "Bob"].max_of { |name| name.length }  #=> 5 (Alice's length)

def min

Returns the element with the minimum value in the collection.

It compares using < so it will work for any type that supports that method.

[1, 2, 3].min         #=> 1
["Alice", "Bob"].min  #=> "Alice"

Raises EmptyEnumerable if the collection is empty.


def min_by(&block : T -> U)

Returns the element for which the passed block returns with the minimum value.

It compares using < so the block must return a type that supports that method

["Alice", "Bob"].min_by { |name| name.length }  #=> "Bob"

Raises EmptyEnumerable if the collection is empty.


def min_of(&block : T -> U)

Like #min_by but instead of the element, returns the value returned by the block.

["Alice", "Bob"].min_of { |name| name.length }  #=> 3 (Bob's length)

def minmax

Returns a tuple with both the minimum and maximum value.

[1, 2, 3].minmax  #=> {1, 3}

Raises EmptyEnumerable if the collection is empty.


def minmax_by(&block : T -> U)

Returns a tuple with both the minimum and maximum values according to the passed block.

["Alice", "Bob", "Carl"].minmax_by { |name| name.length }  #=> {"Bob", "Alice"}

Raises EmptyEnumerable if the collection is empty.


def minmax_of(&block : T -> U)

Returns a tuple with both the minimum and maximum value the block returns when passed the elements in the collection.

["Alice", "Bob", "Carl"].minmax_of { |name| name.length }  #=> {3, 5}

Raises EmptyEnumerable if the collection is empty.


def none?(&block)

Returns true if the passed block returns true for none of the elements of the collection.

[1, 2, 3].none? { |i| i > 5 }  #=> true

It's the opposite of #all?.


def none?

Returns true if all of the elements of the collection are false or nil.

[nil, false].none?        #=> true
[nil, false, true].none?  #=> false

It's the opposite of #all?.


def one?(&block)

Returns true if the passed block returns true for exactly one of the elements of the collection.

[1, 2, 3].one? { |i| i > 2 }  #=> true
[1, 2, 3].one? { |i| i > 1 }  #=> false

def partition(&block)

Returns a tuple with two arrays. The first one contains the elements in the collection for which the passed block returned true, and the second one those for which it returned false.

[1, 2, 3, 4, 5, 6].partition { |i| i % 2 == 0}  #=> {[2, 4, 6], [1, 3, 5]}

def reject(&block : T -> )

Returns an array with all the elements in the collection for which the passed block returns false.

[1, 2, 3, 4, 5, 6].reject { |i| i % 2 == 0}  #=> [1, 3, 5]

def select(&block : T -> )

Returns an array with all the elements in the collection for which the passed block returns true.

[1, 2, 3, 4, 5, 6].select { |i| i % 2 == 0}  #=> [2, 4, 6]

def skip(count : Int)

Returns an array with the first count elements removed from the original collection.

If count is bigger than the number of elements in the collection, returns an empty array.

[1, 2, 3, 4, 5, 6].skip(3)  #=> [4, 5, 6]

def skip_while(&block)

Skips elements up to, but not including, the first element for which the block returns nil or false and returns an array containing the remaining elements.

[1, 2, 3, 4, 5, 0].skip_while {|i| i < 3} #=> [3, 4, 5, 0]

def sum(initial = (typeof(yield first)).zero, &block)

Adds the results of the passed block for each element in the collection.

["Alice", "Bob"].sum { |name| name.length }  #=> 8 (5 + 3)

def sum(initial = T.zero)

Adds all the elements in the collection together.

Only collections of numbers are supported.

[1, 2, 3, 4, 5, 6].sum  #=> 21

An optional initial value can be passed.

[1, 2, 3, 4, 5, 6].sum(100)  #=> 121

def take(count : Int)

Returns an array with the first count elements in the collection.

If count is bigger than the number of elements in the collection, returns as many as possible. This include the case of calling it over an empty collection, in which case it returns an empty array.


def take_while(&block)

Passes elements to the block until the block returns nil or false, then stops iterating and returns an array of all prior elements.

[1, 2, 3, 4, 5, 0].take_while {|i| i < 3} #=> [1, 2]

def to_a

Returns an array with all the elements in the collection.

(1..5).to_a  #=> [1, 2, 3, 4, 5]

def to_h