HOWTO · Ruby

How to Use the inject Method in Ruby

Learn how Ruby's inject method carries an accumulator through a collection to sum values, build hashes, transform strings and objects, and collect matches.

On this page

Ruby’s inject method combines a collection into one result by carrying an accumulator from one element to the next. Use it for operations such as totals, grouped data, and custom aggregates; use join or select when those methods express the task more clearly.

What inject Does in Ruby

inject is an Enumerable method available to arrays and other enumerable collections. reduce is its alias in Ruby; both names use the same behavior. The method returns the final accumulator produced by the block.

How inject Accumulates Values

A block receives the current accumulator and the current element. Its return value becomes the accumulator for the next element. With an explicit initial value, Ruby starts there and processes every element. Without one, the first element becomes the initial accumulator, and the block starts with the second element.

Run this example:

numbers = [1, 2, 3, 4, 5]
total = numbers.inject(0) { |sum, number| sum + number }
puts total
15

This starts sum at 0, adds each number, and prints the accumulated total.

Sum Numbers with inject

For a sum, use 0 as the initial value so the calculation also has a defined starting point when the collection has no elements. The block returns the updated sum on every pass.

prices = [10, 20, 30]
total = prices.inject(0) { |sum, price| sum + price }
puts total
60

For numeric arrays, sum is a more direct choice when you do not need custom accumulation logic. inject is useful when the operation needs additional rules or combines values into a different result type.

Build a Hash with inject

An accumulator can be a mutable object such as a hash. This example counts each word; the final expression in the block returns the hash for the next iteration.

words = ["apple", "banana", "apple"]
counts = words.inject(Hash.new(0)) do |result, word|
  result[word] += 1
  result
end
puts counts.inspect
{"apple"=>2, "banana"=>1}

Hash.new(0) supplies 0 for a word the hash has not seen. Returning result matters: that returned object is carried into the next block call, and the completed hash is the method’s result.

Transform Strings and Custom Objects with inject

For strings, inject can append each part to an accumulator. An array’s join is usually clearer for simple concatenation because it handles separators directly.

words = ["Ruby", "makes", "sense"]
sentence = words.inject("") do |result, word|
  result.empty? ? word : "#{result} #{word}"
end
puts sentence
Ruby makes sense

The accumulator can also derive a value from custom objects. Each object supplies the attribute used in the calculation, while the accumulator remains a number.

Product = Struct.new(:name, :price)
products = [Product.new("Book", 12), Product.new("Pen", 3)]
total_price = products.inject(0) { |sum, product| sum + product.price }
puts total_price
15

This pattern is helpful when an aggregate depends on an object’s attributes. If the objects already provide a direct aggregation method, prefer that method for clarity.

Filter Values with inject

You can build a new array by appending matching values to an array accumulator. For ordinary filtering, select communicates the intent more directly.

numbers = [1, 2, 3, 4, 5, 6]
evens = numbers.inject([]) do |result, number|
  result << number if number.even?
  result
end
puts evens.inspect
[2, 4, 6]

The block returns the same array after each check. select is generally the clearer alternative when the goal is simply to keep elements that match a condition.

Choose an Initial Value and Handle Empty Collections

An explicit initial value determines the accumulator’s type and starting state. Use 0 for a total, an empty string for text, a fresh hash for counts, or an empty array for collected values. This also defines what the operation returns when there are no elements to process.

Without an initial value, the first element supplies the accumulator and is not passed as the block’s current element. Consequently, calling inject without an initial value on an empty collection returns nil; use an initial value when the collection may have no elements or when a particular result type is required. Choose an initial value compatible with the block’s operations so each step can produce a valid next accumulator.

When to Use inject or reduce

Choose inject when a collection must be reduced to one accumulated result and the block makes that transformation clear. reduce is an alias and can be used interchangeably; pick one name and use it consistently. Prefer sum, join, or select when one of those methods states the operation more plainly. For complex accumulation, name the block variables clearly and make sure every path returns the intended next accumulator.