Enumerable provides 60+ iteration methods mixed into Array, Hash, Range, and any class that defines each. It's the core of Ruby's expressive data processing.
| Name | Signature | Description |
|---|---|---|
| each | obj.each {|e| block} → obj | Basic iteration |
| map/collect | obj.map {|e| expr} → Array | Transform to new array |
| select/filter | obj.select {|e| bool} → Array | Keep matching elements |
| reject | obj.reject {|e| bool} → Array | Remove matching elements |
| find/detect | obj.find {|e| bool} → obj | Return first match |
| reduce/inject | obj.reduce(init, :sym) → val | Fold to single value |
| each_with_object | obj.each_with_object(memo) {|e,m|} | Accumulate with memo |
| flat_map | obj.flat_map {|e| Array} → Array | Map then flatten one level |
| group_by | obj.group_by {|e| key} → Hash | Group into hash by key |
| sort_by | obj.sort_by {|e| key} → Array | Sort by computed key |
| min_by/max_by | obj.min_by {|e| key} → element | Find min/max by computed key |
| minmax | obj.minmax → [min, max] | Return [minimum, maximum] |
| count | obj.count {|e| bool} → Integer | Count matching elements |
| tally | obj.tally → Hash | Count each unique element |
| sum | obj.sum {|e| expr} → Number | Sum block results |
| any? | obj.any? {|e| bool} → bool | True if any element matches |
| all? | obj.all? {|e| bool} → bool | True if all elements match |
| none? | obj.none? {|e| bool} → bool | True if no elements match |
| one? | obj.one? {|e| bool} → bool | True if exactly one element matches |
| include? | obj.include?(val) → bool | True if collection contains val |
| each_slice | obj.each_slice(n) {|chunk| block} | Iterate in chunks of n |
| each_cons | obj.each_cons(n) {|window| block} | Sliding window of n |
| zip | obj.zip(*others) → Array | Interleave with other enumerables |
| chunk_while | obj.chunk_while {|a,b| bool} | Group while condition holds |
| take | obj.take(n) → Array | First n elements |
| take_while | obj.take_while {|e| bool} → Array | Take while condition holds |
| drop | obj.drop(n) → Array | Skip first n elements |
| lazy | obj.lazy → Enumerator::Lazy | Create lazy enumerator |
| filter_map | obj.filter_map {|e| expr_or_nil} | Map and filter nils (Ruby 2.7+) |
| flat_map | obj.flat_map {|e| [a,b]} → Array | Map and flatten results |
| each_with_index | obj.each_with_index {|e,i|} | Iterate with integer index |
| to_a/entries | obj.to_a → Array | Convert to array |
Run with ruby script.rb.
# Enumerable — Ruby's most powerful mixin
words = %w[apple banana cherry date elderberry fig grape]
# filter_map (Ruby 2.7+)
long_upper = words.filter_map { |w| w.upcase if w.length > 4 }
puts long_upper.inspect
# each_slice: batches of 3
words.each_slice(3) { |batch| puts batch.inspect }
# each_cons: sliding window
puts "Consecutive pairs:"
[1,2,3,4,5].each_cons(2) { |a,b| print "#{a}+#{b}=#{a+b} " }
puts
# Lazy enumerator — infinite range
result = (1..Float::INFINITY).lazy
.map { |n| n * n }
.select { |n| n > 20 }
.first(5)
puts "First 5 squares > 20: #{result.inspect}"
# chunk_while: group consecutive numbers
nums = [1, 2, 3, 10, 11, 12, 20, 21]
puts nums.chunk_while { |a,b| b - a == 1 }.map(&:inspect).inspect
# Zip + process
names = %w[Alice Bob Carol Dave]
scores = [95, 87, 92, 78]
grade = ->(s) { s >= 90 ? "A" : s >= 80 ? "B" : "C" }
names.zip(scores).map { |n,s| [n, s, grade.(s)] }
.sort_by { |_,s,_g| -s }
.each { |n,s,g| printf "%-8s %d %s\n", n, s, g }
# group_by + transform
puts words.group_by { |w| w.length }
.sort_by { |len,_| len }
.map { |len,ws| "#{len}: #{ws.join(",")}" }
.inspect
# ruby enum_demo.rb