each, map, and select
each, map, and select are the three Enumerable methods you'll reach for most often in everyday Ruby code, and understanding the distinct purpose of each is fundamental to writing idiomatic Ruby. each iterates purely for side effects and returns the original collection unchanged. map (aliased collect) transforms every element and returns a new array of the results. select (aliased filter) returns a new array containing only the elements for which the block returns a truthy value. Confusing these three is one of the most common mistakes new Ruby developers make.
Cricket analogy: A commentator narrating every ball bowled (each) is different from a scorer tallying each ball into a new highlights reel (map), which is different again from a selector filtering only the boundary-hitting balls (select) for a reel.
each: iteration for side effects
each is for when you want to do something with every element — print it, save it, send it somewhere — but don't need a new collection back. Critically, each always returns the original receiver, so chaining .map after .each operates on the original array, not on whatever the block returned.
Cricket analogy: A physio walking down the line checking every player's fitness doesn't hand back a new squad — they still work with the original eleven, just as each always returns the original receiver rather than a new collection.
users = ['Ada', 'Grace', 'Linus']
users.each { |name| puts "Hello, #{name}!" }
#=> prints 3 lines, returns ['Ada', 'Grace', 'Linus'] unchangedmap: transforming every element
map builds and returns a brand-new array where each element is the return value of the block applied to the corresponding original element. The original array is untouched (use the bang variant map! to mutate in place). This is the tool to reach for whenever you need 'the same collection, but every item changed somehow.'
Cricket analogy: Converting a list of raw ball-by-ball deliveries into a list of run totals per over is map — the original delivery list stays untouched, but a brand-new array of totals is built and returned.
prices = [10, 20, 30]
discounted = prices.map { |price| price * 0.9 }
#=> [9.0, 18.0, 27.0]
prices #=> [10, 20, 30] (unchanged)select: filtering elements
select returns a new array containing only the elements for which the block returns something truthy, leaving the count of elements the same or smaller — unlike map, which always preserves the count but can change each value. Its logical opposite is reject, which keeps elements where the block is falsy.
Cricket analogy: Filtering a full over's deliveries down to only the boundaries hit is select — the resulting list can be the same size as the original over or smaller, while reject would keep only the non-boundary balls instead.
scores = [55, 82, 91, 40, 76]
passing = scores.select { |score| score >= 60 }
#=> [82, 91, 76]
failing = scores.reject { |score| score >= 60 }
#=> [55, 40]In JavaScript, these map to forEach, map, and filter respectively — nearly identical semantics, which makes Ruby's Enumerable API feel familiar to JS developers. Python instead favors list comprehensions and generator expressions for map/filter-like transformations, with a built-in map() and filter() that return lazy iterators rather than arrays.
A very common bug: using each when you meant map. result = users.each { |u| u.upcase } returns the original, un-transformed users array, not the upcased names — the block's return value is discarded by each. If you need the transformed values, use map instead.
eachiterates for side effects and always returns the original, unmodified collection.map(aliascollect) returns a new array built from the block's return values, one per element.select(aliasfilter) returns a new array of elements where the block is truthy.rejectisselect's inverse, keeping elements where the block is falsy.- Bang versions (
map!,select!) mutate the receiver in place instead of returning a new array. - Using
eachwhen you actually need transformed output is a frequent beginner mistake.
Practice what you learned
1. What does `each` return after iterating over a collection?
2. What does `map` return?
3. What is the method that returns the logical opposite result of `select`?
4. What is a common bug when a developer uses `each` instead of `map` to transform data?
5. Which method mutates the array in place rather than returning a new array?
Was this page helpful?
You May Also Like
reduce and inject
Understand Ruby's reduce/inject method — how it folds a collection into a single accumulated value, and how to use it for sums, grouping, and building complex results.
Comparable and Enumerable Modules
See how Ruby's Comparable and Enumerable modules let a class gain dozens of methods for free by implementing just one core method each: `<=>` or `each`.
Enumerable Deep Dive
Go beyond map and select to explore Enumerable's full toolkit — sort_by, group_by, partition, each_with_object, lazy enumerators, and more — for expressive collection processing.
Arrays in Ruby
An in-depth look at Ruby's Array class — ordered, index-based collections that can hold mixed types and expose a huge Enumerable-powered method set.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics