Enumerable#reduce

enum.reduce(initial) { |acc, elem| }
Returns: Object · Added in v1.8.7 · Updated March 16, 2026 · Enumerable
ruby enumerable accumulation

The reduce method (also known as inject or fold in other programming languages) accumulates values by applying a binary operation to each element, carrying the result forward until the entire collection is reduced to a single value.

This method is essential for tasks like summing numbers, building strings, finding maximum values, or any operation that combines all elements into one result.

Basic Usage

The simplest form of reduce accumulates all elements using a starting value:

numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(0) { |acc, num| acc + num }
# => 15

The block receives two parameters: the accumulator and the current element. The return value of the block becomes the new accumulator for the next iteration.

Shorthand Symbol Syntax

Ruby provides a convenient shorthand when the operation is a simple method call:

numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(:+)
# => 15

This is equivalent to the block version but more concise. You can use any binary method name as a symbol.

Without Initial Value

If you omit the initial value, reduce uses the first element as the starting accumulator:

numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce { |acc, num| acc + num }
# => 15

Ruby starts with element 1 as the accumulator and then processes elements 2 through 5.

Caution: With an empty collection and no initial value, reduce returns nil:

[].reduce { |acc, x| acc + x }
# => nil

Common Examples

Summing Numbers

prices = [10, 20, 30, 40]
total = prices.reduce(0, :+)
# => 100

Finding Maximum Value

scores = [45, 87, 23, 92, 55]
highest = scores.reduce { |max, score| score > max ? score : max }
# => 92

Building a String

words = ["Hello", "World", "from", "Ruby"]
sentence = words.reduce("") { |str, word| str + word + " " }
# => "Hello World from Ruby "

Flattening Nested Arrays

matrix = [[1, 2], [3, 4], [5, 6]]
flat = matrix.reduce([]) { |acc, arr| acc + arr }
# => [1, 2, 3, 4, 5, 6]

Creating a Hash from Arrays

keys = [:a, :b, :c]
values = [1, 2, 3]
hash = keys.zip(values).reduce({}) { |h, (k, v)| h.merge(k => v) }
# => { a: 1, b: 2, c: 3 }

The inject Alias

inject is an alias for reduce — they behave identically:

[1, 2, 3].reduce(0, :+)
# => 6

[1, 2, 3].inject(0, :+)
# => 6

Many developers prefer reduce because the name more intuitively describes what happens.

Practical Patterns

Factorial Calculation

def factorial(n)
  (1..n).reduce(1, :*)
end

factorial(5)
# => 120

Chaining Transformations

result = [1, 2, 3, 4, 5]
  .reduce([]) { |acc, x| acc << x * 2 }
  .reduce(0, :+)

# => 30

Grouping by Attribute

people = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "Carol", age: 30 }
]

grouped = people.reduce({}) do |acc, person|
  age = person[:age]
  acc[age] ||= []
  acc[age] << person[:name]
  acc
end
# => { 30 => ["Alice", "Carol"], 25 => ["Bob"] }

Performance Notes

reduce is efficient and lazy in the sense that it does not create intermediate collections when using the symbol shorthand. However, for simple sums, specialized methods like sum may be more readable:

# Using reduce
[1, 2, 3].reduce(0, :+)

# Using sum (available in Ruby 2.4+)
[1, 2, 3].sum

Return Value

reduce returns the final accumulated value. For empty collections:

  • With initial value: returns that initial value
  • Without initial value: returns nil

Edge Cases

# Single element with initial value
[5].reduce(10, :+)
# => 15

# Single element without initial value
[5].reduce { |acc, x| acc + x }
# => 5

# With strings (using concatenation)
["a", "b", "c"].reduce(:+)
# => "abc"

See Also