End of Life Ruby 3.1 has reached end of life and gets no more fixes. Switch to Ruby 4.0 →
Enumerable#inject
static VALUE
enum_inject(int argc, VALUE *argv, VALUE obj)
{
struct MEMO *memo;
VALUE init, op;
rb_block_call_func *iter = inject_i;
ID id;
switch (rb_scan_args(argc, argv, "02", &init, &op)) {
case 0:
init = Qundef;
break;
case 1:
if (rb_block_given_p()) {
break;
}
id = rb_check_id(&init);
op = id ? ID2SYM(id) : init;
init = Qundef;
iter = inject_op_i;
break;
case 2:
if (rb_block_given_p()) {
rb_warning("given block not used");
}
id = rb_check_id(&op);
if (id) op = ID2SYM(id);
iter = inject_op_i;
break;
}
if (iter == inject_op_i &&
SYMBOL_P(op) &&
RB_TYPE_P(obj, T_ARRAY) &&
rb_method_basic_definition_p(CLASS_OF(obj), id_each)) {
return ary_inject_op(obj, init, op);
}
memo = MEMO_NEW(init, Qnil, op);
rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
if (memo->v1 == Qundef) return Qnil;
return memo->v1;
}
Returns an object formed from operands via either:
-
A method named by
symbol. -
A block to which each operand is passed.
With method-name argument symbol, combines operands using the method:
# Sum, without initial_operand. (1..4).inject(:+) # => 10 # Sum, with initial_operand. (1..4).inject(10, :+) # => 20
With a block, passes each operand to the block:
# Sum of squares, without initial_operand. (1..4).inject {|sum, n| sum + n*n } # => 30 # Sum of squares, with initial_operand. (1..4).inject(2) {|sum, n| sum + n*n } # => 32
Operands
If argument initial_operand is not given, the operands for inject are simply the elements of self. Example calls and their operands:
(1..4).inject(:+)-
[1, 2, 3, 4].
(1...4).inject(:+)-
[1, 2, 3].
('a'..'d').inject(:+)-
['a', 'b', 'c', 'd'].
('a'...'d').inject(:+)-
['a', 'b', 'c'].
Examples with first operand (which is self.first) of various types:
# Integer. (1..4).inject(:+) # => 10 # Float. [1.0, 2, 3, 4].inject(:+) # => 10.0 # Character. ('a'..'d').inject(:+) # => "abcd" # Complex. [Complex(1, 2), 3, 4].inject(:+) # => (8+2i)
If argument initial_operand is given, the operands for inject are that value plus the elements of self. Example calls their operands:
(1..4).inject(10, :+)-
[10, 1, 2, 3, 4].
(1...4).inject(10, :+)-
[10, 1, 2, 3].
('a'..'d').inject('e', :+)-
['e', 'a', 'b', 'c', 'd'].
('a'...'d').inject('e', :+)-
['e', 'a', 'b', 'c'].
Examples with initial_operand of various types:
# Integer. (1..4).inject(2, :+) # => 12 # Float. (1..4).inject(2.0, :+) # => 12.0 # String. ('a'..'d').inject('foo', :+) # => "fooabcd" # Array. %w[a b c].inject(['x'], :push) # => ["x", "a", "b", "c"] # Complex. (1..4).inject(Complex(2, 2), :+) # => (12+2i)
Combination by Given Method
If the method-name argument symbol is given, the operands are combined by that method:
-
The first and second operands are combined.
-
That result is combined with the third operand.
-
That result is combined with the fourth operand.
-
And so on.
The return value from inject is the result of the last combination.
This call to inject computes the sum of the operands:
(1..4).inject(:+) # => 10
Examples with various methods:
# Integer addition. (1..4).inject(:+) # => 10 # Integer multiplication. (1..4).inject(:*) # => 24 # Character range concatenation. ('a'..'d').inject('', :+) # => "abcd" # String array concatenation. %w[foo bar baz].inject('', :+) # => "foobarbaz" # Hash update. h = [{foo: 0, bar: 1}, {baz: 2}, {bat: 3}].inject(:update) h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3} # Hash conversion to nested arrays. h = {foo: 0, bar: 1}.inject([], :push) h # => [[:foo, 0], [:bar, 1]]
Combination by Given Block
If a block is given, the operands are passed to the block:
-
The first call passes the first and second operands.
-
The second call passes the result of the first call, along with the third operand.
-
The third call passes the result of the second call, along with the fourth operand.
-
And so on.
The return value from inject is the return value from the last block call.
This call to inject gives a block that writes the memo and element, and also sums the elements:
(1..4).inject do |memo, element| p "Memo: #{memo}; element: #{element}" memo + element end # => 10
Output:
"Memo: 1; element: 2" "Memo: 3; element: 3" "Memo: 6; element: 4"
Enumerable#reduce is an alias for Enumerable#inject.