GGistDev

Iterators and Enumerables in Ruby

Expressive collection processing via Enumerable and iterator methods.

Core methods

map, select, reject, and reduce cover most transforms and folds.

[1,2,3].map { |n| n * 2 }          # => [2,4,6]
[1,2,3,4].select(&:even?)          # => [2,4]
[1,2,3].reduce(0, :+)              # => 6

Queries and search

Predicates and search helpers return booleans or single elements.

[1,2,3].any?(&:odd?)                 # => true
[1,2,3].all? { |n| n > 0 }           # => true
[1,2,3].find(&:even?)                # => 2
[1,2,3].none?(&:negative?)           # => true

Reshaping collections

Group, partition, chunk, sort, and accumulate into objects.

%w[ant bat cat].group_by { |w| w.size }   # => {3=>["ant","bat","cat"]}
[1,2,3,4].partition(&:even?)              # => [[2,4],[1,3]]
(1..7).each_slice(3).to_a                 # => [[1,2,3],[4,5,6],[7]]
[3,1,2].sort_by { |n| -n }                # => [3,2,1]
[1,2,3].each_with_object({}) { |n, h| h[n] = n*n }

Enumerators and chaining

Most methods return an Enumerator when no block is given; you can chain or iterate later.

(1..).lazy.select(&:odd?).map { |n| n*n }.take(5).to_a

Custom enumerables

Include Enumerable and define each to gain the full toolkit.

class Bag
  include Enumerable
  def initialize(items) @items = items end
  def each(&blk) @items.each(&blk) end
end

Summary

  • Reach for map/select/reduce first
  • Use group_by, partition, and each_slice to reshape data
  • Enumerators enable lazy pipelines and advanced control