Array#sum
The .sum method calculates the total of all elements in an array. It is part of the Enumerable module, so it works on arrays, ranges, and hashes. Ruby added this method in version 2.4 to provide a simpler alternative to inject(:+) for common summation tasks.
# Basic usage
numbers = [1, 2, 3, 4, 5]
numbers.sum
# => 15
# With initial value
numbers.sum(10)
# => 25
# With ranges
(1..100).sum
# => 5050
Syntax
array.sum
array.sum(initial)
array.sum(initial) { |element| block }
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
initial | Object | 0 (for numbers) | Starting value for the sum. Defaults to zero for numeric arrays, empty string for string arrays. |
| block | Block | None | Optional block to transform each element before summing. |
What .sum Returns
.sum returns the total as a number by default. The return type matches the input type plus the initial value:
[1, 2, 3].sum
# => 6 (Integer)
[1.5, 2.5, 3.0].sum
# => 7.0 (Float)
Examples
Basic Numeric Summation
prices = [29.99, 14.99, 9.99, 49.99]
prices.sum
# => 104.96
# Sum of a range
(1..1000).sum
# => 500500
With Initial Value
The initial value lets you offset the sum or use it as a accumulator for more complex operations:
# Start from a different number
[1, 2, 3].sum(10)
# => 16
# Accumulate across multiple arrays
total = [1, 2, 3].sum
total += [4, 5, 6].sum
total += [7, 8, 9].sum
# => 45
With a Block
Pass a block to transform elements before summing:
# Square each number before summing
(1..4).sum { |i| i * i }
# => 30 (1 + 4 + 9 + 16)
# Sum only even numbers
(1..10).sum { |n| n.even? ? n : 0 }
# => 30 (2 + 4 + 6 + 8 + 10)
# With initial value and block
(1..4).sum(100) { |i| i * i }
# => 130 (100 + 1 + 4 + 9 + 16)
With Hashes
scores = { alice: 85, bob: 92, carol: 78 }
# Sum values
scores.sum { |_name, score| score }
# => 255
# Sum with transformation
scores.sum(0) { |name, score| name.to_s.length + score }
# => 266 (5 + 85 + 3 + 92 + 5 + 78)
With Strings
# Concatenate strings
["hello", "world"].sum("")
# => "helloworld"
# With initial string
["a", "b", "c"].sum("prefix-")
# => "prefix-abc"
# With block
["cat", "dog", "bird"].sum("") { |word| word[0].to_s }
# => "cdb" (first character of each)
Common Patterns
Calculating Averages
Combine .sum with .count to calculate averages:
grades = [85, 90, 78, 92, 88]
average = grades.sum / grades.count
# => 86
Conditional Sum
Use a block to sum only matching elements:
transactions = [100, -50, 200, -25, 150]
# Sum only positive transactions
income = transactions.sum { |t| t > 0 ? t : 0 }
# => 450
# Sum only negative (expenses)
expenses = transactions.sum { |t| t < 0 ? t : 0 }
# => -75
Weighted Sums
values = [10, 20, 30]
weights = [0.5, 0.3, 0.2]
weighted_sum = values.map.with_index { |v, i| v * weights[i] }.sum
# => 17.0
Performance
The .sum method has built-in optimizations. For consecutive integer ranges, Ruby uses Gauss’s summation formula:
# Ruby optimizes this to n(n+1)/2
(1..1000000).sum
# => 500000500000 (instant, not a loop)
For large arrays of numbers, .sum is faster than inject(:+) because it bypasses some of the Enumerable overhead.
Gotchas
Empty Arrays Return Initial Value
[].sum
# => 0
[].sum(100)
# => 100
Float Precision
[0.1, 0.2].sum
# => 0.30000000000000004 (floating point quirk)
Block Overrides Initial for First Element
When using a block, the initial value is still added once at the end, not used as the starting accumulator:
[1, 2, 3].sum(10) { |n| n * 2 }
# => 10 + (1*2 + 2*2 + 3*2) = 10 + 12 = 22
See Also
.inject / .reduce— More flexible accumulation method.map— Transform elements before summing.count— Count elements matching a condition