最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ruby - Inject behavior when last element is used before referencing accumulator - Stack Overflow

programmeradmin3浏览0评论

I am a a bit confused by some of the behavior of the of the inject (alias reduce) command in Ruby

Background

For any array, the second element (referenced after the accumulator) reflects the last element in the array so
[1,2,10].inject{|accumulator,y| y} gives 10

whereas the first element is the initial value of the array (that subsequently gets the result of any specified operation) if not otherwise specified so
[1,2,10].inject{|accumulator,y| accumulator} gives 1

Addition

This results in the expected behavior for
[1,2,10].inject{|accumulator,y| accumulator + y} gives 13
OR
[1,2,10].inject{|accumulator,y| y + accumulator} gives 13

However,

If a string is used
["b","i","g"].inject{|x,y| y + x} the result is "gib".
Why is it not "gbi"?
I would expect (last element + first element)+ i OR ("g"+"b")+ "i"

Subtraction

It also works as expected for subtraction when x is the value to be acted on first
[1,2,10].inject{|x,y| x - y} gives -11 i.e (1-2) - 10 = -11 as expected

However,

when 'y' is the first element to be acted on

[1,2,10].inject{|x,y| y - x} gives -9.
This is surprising. Only the last element and the first are used i.e 10-1.
Why is there is no accumulated result?!

I am a a bit confused by some of the behavior of the of the inject (alias reduce) command in Ruby

Background

For any array, the second element (referenced after the accumulator) reflects the last element in the array so
[1,2,10].inject{|accumulator,y| y} gives 10

whereas the first element is the initial value of the array (that subsequently gets the result of any specified operation) if not otherwise specified so
[1,2,10].inject{|accumulator,y| accumulator} gives 1

Addition

This results in the expected behavior for
[1,2,10].inject{|accumulator,y| accumulator + y} gives 13
OR
[1,2,10].inject{|accumulator,y| y + accumulator} gives 13

However,

If a string is used
["b","i","g"].inject{|x,y| y + x} the result is "gib".
Why is it not "gbi"?
I would expect (last element + first element)+ i OR ("g"+"b")+ "i"

Subtraction

It also works as expected for subtraction when x is the value to be acted on first
[1,2,10].inject{|x,y| x - y} gives -11 i.e (1-2) - 10 = -11 as expected

However,

when 'y' is the first element to be acted on

[1,2,10].inject{|x,y| y - x} gives -9.
This is surprising. Only the last element and the first are used i.e 10-1.
Why is there is no accumulated result?!

Share Improve this question asked 16 hours ago Ricman RRicman R 113 bronze badges 1
  • The docs for inject explain how it works. (hint: the block in your examples is called more than once) – Stefan Commented 10 hours ago
Add a comment  | 

1 Answer 1

Reset to default 3

For any array, the second element (referenced after the accumulator) reflects the last element in the array

This incorrect statement is the source of the misunderstanding.

Look at the following code:

["b", "i", "g"].inject do |x, y|
  puts({x: x, y: y, "y + x": (y + x) })
  y + x
end

which prints

{x: "b", y: "i", "y + x": "ib"}
{x: "ib", y: "g", "y + x": "gib"}

As you can see, the second block parameter isn't the last element in the array, it's the next element in the array. ["b", "i", "g"].inject uses "b" as the first accumulator and passes "i", then "g".


[1,2,10].inject{|x,y| y - x} gives -9

Are you sure? When I run that code, it returns 9 (which is 10 - (2 - 1)). In any case, you can add the same puts statement to observe how it proceeds.

发布评论

评论列表(0)

  1. 暂无评论