method

inject

v1_8_7_330 - Show latest stable - Class: Enumerable
inject(...)
public

enum.reduce(initial, sym) => obj enum.reduce(sym) => obj enum.reduce(initial) {| memo, obj | block } => obj enum.reduce {| memo, obj | block } => obj

Combines all elements of <i>enum</i> by applying a binary
operation, specified by a block or a symbol that names a
method or operator.

If you specify a block, then for each element in <i>enum<i>
the block is passed an accumulator value (<i>memo</i>) and the element.
If you specify a symbol instead, then each element in the collection
will be passed to the named method of <i>memo</i>.
In either case, the result becomes the new value for <i>memo</i>.
At the end of the iteration, the final value of <i>memo</i> is the
return value fo the method.

If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
then uses the first element of collection is used as the initial value
of <i>memo</i>.

Examples:

# Sum some numbers (5..10).reduce(:+) #=> 45 # Same using a block and inject (5..10).inject {|sum, n| sum + n } #=> 45 # Multiply some numbers (5..10).reduce(1, :*) #=> 151200 # Same using a block (5..10).inject(1) {|product, n| product * n } #=> 151200 # find the longest word longest = %w{ cat sheep bear }.inject do |memo,word|

memo.length > word.length ? memo : word

end longest #=> “sheep”

9Notes

Parameters for Hash#inject

tadman · Apr 16, 200915 thanks

When running inject on a Hash, the hash is first converted to an array before being passed through.

The typical Enumerable#inject approach would be to simply capture the value:

array.inject(...) do |c, v|
end

In the case of a Hash, v is actually a key/value pair Array. That is the key is v.first and the value is v.last, however using the pair this way is awkward and can lead to confusion.

Better to simply expand the parameters in the block definition:

hash.inject(...) do |c, (k, v)|
end

Where c is the traditional carry variable and k/v represent key and value respectively.

Re: Convert an Array of Arrays to a Hash using inject

LacKac · Aug 17, 20086 thanks

If you're sure you have a two-level array (no other arrays inside the pairs) and exactly two items in each pair, then it's faster and shorter to use this:

array = [['A', 'a'], ['B', 'b'], ['C', 'c']]
hash = Hash[*array.flatten]

For more than two-level deep arrays this will give the wrong result or even an error (for some inputs).

array = [['A', 'a'], ['B', 'b'], ['C', ['a', 'b', 'c']]]
hash = Hash[*array.flatten]
# => {"A"=>"a", "B"=>"b", "C"=>"a", "b"=>"c"}

But if you're running Ruby 1.8.7 or greater you can pass an argument to Array#flatten and have it flatten only one level deep:

# on Ruby 1.8.7+
hash = Hash[*array.flatten(1)]
# => {"A"=>"a", "B"=>"b", "C"=>["a", "b", "c"]}

Convert an Array of Arrays to a Hash using inject

Olly · Aug 14, 20085 thanks

Converting an array of arrays to a hash using inject: array = [['A', 'a'], ['B', 'b'], ['C', 'c']]

hash = array.inject({}) do |memo, values|
memo[values.first] = values.last
memo
end

hash
# => {'A' => 'a', 'B' => 'b', 'C' => 'c'}

From the official docs

pervel · Dec 2, 20085 thanks
enum.inject(initial) {| memo, obj | block } => obj  
enum.inject {| memo, obj | block } => obj

Combines the elements of enum by applying the block to an accumulator value (memo) and each element in turn. At each step, memo is set to the value returned by the block. The first form lets you supply an initial value for memo. The second form uses the first element of the collection as a the initial value (and skips that element while iterating).

Sum some numbers

(5..10).inject {|sum, n| sum + n } #=> 45

Multiply some numbers

(5..10).inject(1) {|product, n| product * n } #=> 151200

find the longest word

longest = %w{ cat sheep bear }.inject do |memo,word| memo.length > word.length ? memo : word end longest #=> "sheep"

find the length of the longest word

longest = %w{ cat sheep bear }.inject(0) do |memo,word| memo >= word.length ? memo : word.length end longest #=> 5

http://www.ruby-doc.org/core/classes/Enumerable.html

Array expansion in blocks

nachocab · Dec 6, 20085 thanks

The syntax can be improved as changing the second parameter of the block (values) and using an array of two variables instead, which will be used by Ruby as the key and value of "array". array = [['A', 'a'], ['B', 'b'], ['C', 'c']]

hash = array.inject({}) do |memo, (key, value)|
memo[key] = value
memo
end

hash
# => {'A' => 'a', 'B' => 'b', 'C' => 'c'}

Calculating on an enumerable

Mange · Feb 9, 20092 thanks

Inject can easily be used to sum an enumerable or to get the product of it [100, 200, 1000].inject(0) { |sum, value| sum += value } # => 1300 [100, 200, 1000].inject(1) { |sum, value| sum *= value } # => 20000000

# You can access members and move down in the data structures, too
points.inject(0) { |sum, point| sum += point.y }

In the case of the first two examples, an easier way to do it in Ruby 1.9 is to use reduce: [100, 200, 1000].reduce :+ # => 1300 [100, 200, 1000].reduce :* # => 20000000

Look at reduce for more examples on how to use this.

Highlight keywords in a text

zoopzoop · Jul 17, 20091 thank

Case-insensitive

keywords.inject(text) { |text, keyword| text.gsub(/(#{keyword})/i, "<strong>\\\\1</strong>") }

can be replace by whatever HTML tag you want for hightlighting (, , ...)

RE: Convert an Array of Arrays to a Hash using inject

dantealg · May 12, 2015

==== Another way to convert an array of arrays to a hash using inject:

array = [['A', 'a'], ['B', 'b'], ['C', 'c']]

hash = array.inject({}) do |memo, values|
memo.merge!(values.first => values.last)
end

hash
# => {'A' => 'a', 'B' => 'b', 'C' => 'c'}