Skip to content
AgileLogics
6 min read

map, select, and reduce

Prerequisites: Blocks

These block-taking methods replace most hand-written loops in Ruby. They work on arrays, hashes, ranges, and anything else that's enumerable (can be iterated).

map — transform every element

map runs the block on each element and returns a new array of the results:

prices = [10, 20, 30]
with_tax = prices.map { |price| price * 1.2 }
p with_tax
[12.0, 24.0, 36.0]

select and reject — filter

nums = (1..10).to_a
p nums.select { |n| n.even? }
p nums.reject(&:even?)
p nums.find { |n| n > 4 }
[2, 4, 6, 8, 10]
[1, 3, 5, 7, 9]
5

select keeps elements where the block is truthy; reject removes them; find returns only the first match (or nil).

reduce — combine into one value

reduce walks the collection, carrying an accumulator along:

nums = [1, 2, 3, 4]
total = nums.reduce(0) { |sum, n| sum + n }
p total
10

The accumulator (sum) starts at 0; each pass returns the new accumulator. For simple cases there are ready-made methods: sum, min, max, count.

More everyday helpers

words = %w[apple avocado banana cherry blueberry]

p words.group_by { |w| w[0] }
p words.sort_by(&:length)
p words.any? { |w| w.start_with?("c") }
p words.all? { |w| w.length > 3 }
p %w[a b a c a].tally
{"a" => ["apple", "avocado"], "b" => ["banana", "blueberry"], "c" => ["cherry"]}
["apple", "banana", "cherry", "avocado", "blueberry"]
true
true
{"a" => 3, "b" => 1, "c" => 1}

Chaining

These methods return new collections, so they chain naturally:

orders = [120, 45, 300, 80]
big_total = orders.select { |o| o > 100 }.map { |o| o * 0.9 }.sum
p big_total
378.0

Common mistakes

  • Using each when you want a result. each returns the original array, not the block's results — use map.
  • Using select when you only need the first match. find stops as soon as it finds one.

Practice

Given names = ["ada", "linus", "grace", "al"], produce an array of the names longer than 2 letters, capitalized.

Show solution
names = ["ada", "linus", "grace", "al"]
p names.select { |n| n.length > 2 }.map(&:capitalize)
["Ada", "Linus", "Grace"]