需要注入方法的简单说明

135 ruby syntax

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
Run Code Online (Sandbox Code Playgroud)

我正在看这个代码,但我的大脑没有记录数字10如何成为结果.有人会介意解释这里发生了什么吗?

Dre*_*son 198

您可以将第一个块参数视为累加器:块的每次运行的结果都存储在累加器中,然后传递给块的下一次执行.在上面显示的代码的情况下,您将累加器,结果默认为0.每次运行该块将给定的数字添加到当前总数,然后将结果存储回累加器.下一个块调用具有此新值,添加,再次存储并重复.

在该过程结束时,inject返回累加器,在这种情况下,累加器是数组中所有值的总和,或10.

这是另一个从对象数组创建哈希的简单示例,由其字符串表示键入:

[1,"a",Object.new,:hi].inject({}) do |hash, item|
  hash[item.to_s] = item
  hash
end
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们将累加器默认为空哈希,然后在每次执行块时填充它.请注意,我们必须将散列作为块的最后一行返回,因为块的结果将存储回累加器中.

  • @Projjol“结果+解释”既是对累加器的转换又是返回值。这是块中的最后一行,使其成为隐式返回。 (2认同)

Bri*_*ell 83

inject取值一个值(0在你的例子中)和一个块,它为列表的每个元素运行一次该块.

  1. 在第一次迭代中,它传递您提供的值作为起始值,并传递列表的第一个元素,并保存块返回的值(在本例中result + element).
  2. 然后它再次运行块,将第一次迭代的结果作为第一个参数传递,将列表中的第二个元素作为第二个参数传递,再次保存结果.
  3. 它继续这种方式,直到它消耗了列表的所有元素.

解释这一点的最简单方法可能是展示每个步骤的工作原理,例如; 这是一组虚构的步骤,显示了如何评估此结果:

[1, 2, 3, 4].inject(0) { |result, element| result + element }
[2, 3, 4].inject(0 + 1) { |result, element| result + element }
[3, 4].inject((0 + 1) + 2) { |result, element| result + element }
[4].inject(((0 + 1) + 2) + 3) { |result, element| result + element }
[].inject((((0 + 1) + 2) + 3) + 4) { |result, element| result + element }
(((0 + 1) + 2) + 3) + 4
10
Run Code Online (Sandbox Code Playgroud)

  • 下图基于*如何实现*; 它不一定以这种方式实现.这就是为什么我说这是一个想象中的一系列步骤; 它演示了基本结构,但没有说明确切的实现. (2认同)

Vis*_*gda 27

inject方法的语法如下:

inject (value_initial) { |result_memo, object| block }

让我们解决上面的例子即

[1, 2, 3, 4].inject(0) { |result, element| result + element }

它给出10作为输出.

因此,在开始之前,让我们看看每个变量中存储的值是什么:

result = 0零来自注入(值),即0

element = 1它是数组的第一个元素.

好!!!那么,让我们开始理解上面的例子

步骤1 [1, 2, 3, 4].inject(0) { |0, 1| 0 + 1 }

第2步 [1, 2, 3, 4].inject(0) { |1, 2| 1 + 2 }

步骤:3 [1, 2, 3, 4].inject(0) { |3, 3| 3 + 3 }

第4步 [1, 2, 3, 4].inject(0) { |6, 4| 6 + 4 }

步骤:5 [1, 2, 3, 4].inject(0) { |10, Now no elements left in the array, so it'll return 10 from this step| }

这里Bold-Italic值是从数组中获取的元素,而简单的Bold值是结果值.

我希望你了解该#inject方法的工作原理#ruby.


Joh*_*ley 18

代码迭代数组中的四个元素,并将先前的结果添加到当前元素:

  • 1 + 2 = 3
  • 3 + 3 = 6
  • 6 + 4 = 10


Mik*_*use 15

他们说了什么,但也要注意你并不总是需要提供"起始价值":

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10
Run Code Online (Sandbox Code Playgroud)

是相同的

[1, 2, 3, 4].inject { |result, element| result + element } # => 10
Run Code Online (Sandbox Code Playgroud)

试试吧,我等一下.

当没有参数传递给inject时,前两个元素被传递给第一次迭代.在上面的示例中,结果为1,第一次元素为2,因此对块进行少量调用.


小智 14

你在注入()中的数字代表一个起始位置,它可以是0或1000.在管道内你有两个占位符| x,y |.x = .inject('x')中的数字,而secound表示对象的每次迭代.

[1, 2, 3, 4].inject(5) { |result, element| result + element } # => 15

1 + 5 = 6 2 + 6 = 8 3 + 8 = 11 11 + 4 = 15


Jon*_*son 6

注入应用块

result + element
Run Code Online (Sandbox Code Playgroud)

到数组中的每个项目.对于下一个项目("元素"),从块返回的值是"result".你调用它的方式(带参数),"result"以该参数的值开始.因此效果是添加元素.


IAm*_*NaN 6

tldr; injectmap一个重要方式不同:inject返回块的最后一次执行的值,而map返回它迭代的数组.

不止于每个块执行的值通过第一个参数传递到下一个执行(result在这种情况下),您可以初始化该值(该(0)部分).

您可以使用map以下方式编写上面的示例:

result = 0 # initialize result
[1, 2, 3, 4].map { |element| result += element }
# result => 10
Run Code Online (Sandbox Code Playgroud)

相同的效果,但inject在这里更简洁.

您经常会在map块中发现赋值,而块中会进行评估inject.

您选择哪种方法取决于您想要的范围result.何时使用它将是这样的:

result = [1, 2, 3, 4].inject(0) { |x, element| x + element }
Run Code Online (Sandbox Code Playgroud)

你可能就像所有人一样,"看起来我,我只是把它们全部组合成一行",但是你也暂时将内存分配x为一个临时变量,因为你已经不得不result使用它了.


nop*_*ole 5

这是一个简单且相当容易理解的解释:

\n

忘记“初始值”,因为它一开始有点令人困惑。

\n
> [1,2,3,4].inject{|a,b| a+b}\n=> 10\n
Run Code Online (Sandbox Code Playgroud)\n

你可以把上面理解为:我在1,2,3,4之间注入一个“加法机”。意思是,它是 1 \xe2\x99\xab 2 \xe2\x99\xab 3 \xe2\x99\xab 4 并且 \xe2\x99\xab 是一个加法机,所以它与 1 + 2 + 3 + 相同4,现在是10了。

\n

你实际上可以+在它们之间注入一个:

\n
> [1,2,3,4].inject(:+)\n=> 10\n
Run Code Online (Sandbox Code Playgroud)\n

就像+在 1,2,3,4 之间注入 a,使其成为 1 + 2 + 3 + 4,结果是 10。这:+是 Ruby+以符号形式指定的方式。

\n

这是非常容易理解和直观的。如果你想一步步分析它是如何工作的,就像:取1和2,然后将它们相加,当你有结果时,先存储它(即3),现在,下一个是存储的值 3 和数组元素 3 经过 a + b 过程,即 6,现在存储该值,现在 6 和 4 经过 a + b 过程,结果是 10。你本质上是在做

\n
((1 + 2) + 3) + 4\n
Run Code Online (Sandbox Code Playgroud)\n

是 10。“初始值”0只是一个“基数”。在许多情况下,您不需要它。想象一下,如果您需要 1 * 2 * 3 * 4 并且它是

\n
[1,2,3,4].inject(:*)\n=> 24\n
Run Code Online (Sandbox Code Playgroud)\n

一切都完成了。您不需要1将整个值与 相乘的“初始值” 1。这一次,它正在做

\n
(((1 * 2) * 3) * 4)\n
Run Code Online (Sandbox Code Playgroud)\n

你得到的结果与

\n
1 * 2 * 3 * 4\n
Run Code Online (Sandbox Code Playgroud)\n