关于注入方法:它是如何工作的?

时间:2017-02-16 01:50:13

标签: ruby

这部分代码计算每个算术系列的值,包括用户输入的数字:

print "enter a number: "
num = gets.to_i
(1..num).inject(0) do |res, e|
  res += e
  p res
end

我认为(1..num)是范围,num是用户输入。我知道inject通过应用由块或命名方法或运算符的符号指定的二进制运算来组合枚举的所有元素。

我不明白这一行中每个元素的作用:

(1..num).inject(0) do |res, e|
  • |res, e|是什么意思?它必须是定义inject所做内容的块,但实例rese代表什么? (e可能是元素?)
  • (0)代表什么?
  • 命令do做了什么?
  • 关于(1..num)inject(0)
  • 的联系是什么?
  • 我是否正确地认为最后p代表putsprint

3 个答案:

答案 0 :(得分:5)

inject采用可选的起始值,并采用中间值和元素并返回新的中间值。

所以:

  

(0)代表什么?

inject的起始值参数。

  

命令“做”是做什么的?

这不是命令;它标志着块的开始(由end终止)。 .inject(0) do ... end几乎(除了一些语法问题)与.inject(0) { ... }相同。通常,do ... end用于多行块,{ ... }用于单行块,但不是常规。

  

什么是| res,e |意思?

这些是块参数(中间值和当前元素),这里可能分别在“result”和“element”之后调用。

让我们看一个简化的例子:(1..3).inject(0) do |res, e| res + e end将中间结果设置为0。然后它将传递此中间结果并注入可枚举的第一个元素:res0e1。块的值是其最后一个表达式的值,即10 + 1的结果)。此1现在成为新的中间值,2成为下一个当前元素。该块的值为31 + 2的结果)。在下一次迭代中,中间值为3,当前元素也为3,从而产生63 + 3)。当我们到达其上边界时,范围将停止产生元素,inject返回计算的最后一个中间结果6

  

另外,最后一个问题我是否可以假设最后的“p”代表看跌或打印?

几乎。 p是它自己的野兽。 p x大致与puts x.inspect; x同义 - 即它以不同的格式打印值,而不像puts总是返回nilp返回值不变。因此,块结尾处的p res不会通过使代码返回nil来销毁代码,而是透明地返回res

答案 1 :(得分:3)

inject是一种将集合(例如数组或范围)简化为单个值的方法。它通过对集合中的每个元素执行一次块来完成此操作。该块有两个参数:正在处理的当前值,以及最终将返回的单个值。 inject本身接受一个参数(除了块),这是它的初始起始值。

举个例子。

x = [1, 2, 3, 4, 5].inject(0) do |result, current|
  result + current
end

我们有一个数字列表[1, 2, 3, 4, 5]。我们要将它们煮成一个数字。

我们从0开始,因为那是inject的论点。这意味着第一次运行块时,result将为0。

所以该块第一次运行。 result为0,current为1,即第一个元素。我们说result + current1)。它是块内的最后一个表达式,所以它就是'块'返回'。

在阻止结束时,inject说“好吧,我们在集合中有更多元素吗?”是啊。所以块再次运行。 这次result是最后一个块返回的内容,即1,current是第二个元素2

块运行,并以result + current或1 + 2结束,即3。仍有剩余元素,因此我们再次运行。这一次,result为3,current为3 result + current,6。还有更多值,下次运行时result为6 {{1} }是4. 6 + 4 = 10.还有更多的值,在下次运行时current是10而result是5. 10 + 5 = 15.

然后块完成,并且没有剩余元素。所以current本身返回的是最终值15.最后,inject。我们通过添加内容将我们的列表归结为一个数字。

示例中的

x = 15代表结果,res代表元素。你可以随便给他们打电话。您可以在添加时调用e,或者如果相乘则调用sum。但他们不一定是数字。你可以使用product来煮沸一个字符串数组,一系列字符,一个数组数组,你想要的任何集合。该块只是告诉它如何。

答案 2 :(得分:1)

很高兴看到你正在学习Ruby,欢迎!

在您的专业水平上,最好从书中学习。

一些快速回答

  • 1..num是范围对象
  • .inject(0) do ... end是一个带有两个参数的方法调用,值0和代码块
  • do |a, b| ... end是包含两个参数的代码块
  • rese是非常糟糕的变量名称,可能更好地使用sumeach
  • p是一个打印调试信息的全局方法,类似于puts但不一样

希望有助于解锁你。