|m,k| 事情有点让我失望。这与优先顺序有什么关系吗?m 代表 0(或某些语言中的 1)和 k 代表 Array/Hash 中的最后一个?
那么为什么人们在 .inject() 中输入一个数字呢?
或者,是否有一种简单的方法来学习如何使用它,以及它的价值到底是什么?从这个问题来看,我希望你们都知道我对任何编程语言都非常陌生,而 Ruby 是我的第一选择。
|m,k| 事情有点让我失望。这与优先顺序有什么关系吗?m 代表 0(或某些语言中的 1)和 k 代表 Array/Hash 中的最后一个?
那么为什么人们在 .inject() 中输入一个数字呢?
或者,是否有一种简单的方法来学习如何使用它,以及它的价值到底是什么?从这个问题来看,我希望你们都知道我对任何编程语言都非常陌生,而 Ruby 是我的第一选择。
让我们尝试一个例子。
numbers = [ 3, 1, 4, 1, 5, 9 ]
sum = numbers.inject(0) do |prefix_sum, number|
prefix_sum + number
end
#inject
接受一个参数和一个块。该块应采用两个值,并返回一个新值。
在上面的例子中,参数#inject
是0
,块是do |prefix_sum, number| prefix_sum + number end
。将传递给块的值在两个|
标记之间命名:prefix_sum
和number
。
被调用的可枚举的每个值都#inject
作为第二个值依次传递给块。在此示例number
中将是3
, then 1
, then 4
, then 1
, then 5
, then finally 9
。所以在这个例子中,该块将被调用六次;中的每个位置一次numbers
。
传递给块(此处命名为prefix_sum
)的第一个值通常称为累加器。它的初始值,即第一次调用块时使用的值,#inject
由传递给的参数设置#inject
(在本例中为0
)。块的返回值决定了prefix_sum
下一次调用块的累加器 ( ) 的值。
当没有更多元素要处理时,返回累加器的值(并存储在此处sum
)。
所以让我们来看看它:
#inject
接收0
和我们的块。#inject
调用我们的块,绑定prefix_sum
到0
(初始累加器值)和number
(3
第一个数组值)。0+3
as3
并返回它。#inject
调用我们的块,绑定prefix_sum
到3
(返回值)和number
(1
第二个数组值)3+1
as4
并返回它。#inject
调用我们的块,绑定prefix_sum
到4
(返回值)和number
(4
第三个数组值)4+4
as8
并返回它。#inject
调用我们的块,绑定prefix_sum
到8
(返回值)和number
(1
第四个数组值)8+1
as9
并返回它。#inject
调用我们的块,绑定prefix_sum
到9
(返回值)和number
(5
第五个数组值)9+5
as14
并返回它。#inject
调用我们的块,绑定prefix_sum
到14
(返回值)和number
(9
第六个数组值)14+9
as23
并返回它。#inject
返回23
,我们绑定sum
到那个值。您可以将注入视为对项目列表进行括号操作,在此示例中,计算:
((((((0 + 3) + 1) + 4) + 1) + 5) + 9)
这使您可以进行通常仅对一对参数进行操作的任何操作,并将其应用于列表。
您似乎将块参数与方法参数混淆了。
传入inject() 方法的人数是一个方法参数,当你使用|m,k| 时,它决定了“m”的初始值。为块。我不知道你在哪里看到它们命名为 m 和 k,也不知道它们为什么这样命名,但这肯定不是因为它们代表第一个和最后一个元素。
以 kjfletch 的链接中描述的方式查看它会更简单,inject() 的分解,其中它们被命名为“结果”和“元素”。
使用 inject() 的价值在于简洁。任何你想用 inject() 做的事情也可以通过调用 each() 方法来完成,使用更长的块和额外的变量声明。请参阅此问题和答案以了解它。
如果您想了解任何方法在 Ruby 中的作用,可以使用捆绑ri
工具(因此您可以键入“ri Enumerable.inject”来查找文档)或搜索Ruby-Doc。在这种情况下,您会看到:
通过将块应用于累加器值(备忘录)和每个元素依次组合枚举的元素。在每一步,memo 都设置为块返回的值。第一种形式允许您为备忘录提供初始值。第二种形式使用集合的第一个元素作为初始值(并在迭代时跳过该元素)。
# 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
为了完整起见:m通常表示memo;k可能表示键(通常与v一起使用,表示值)。因此,例如:
stuff.inject({}) { |m,(k,v)| m.merge(k.to_sym => v) }
我还看到人们使用a for accumulator和e for element,像这样:
numbers.inject { |a,e| a+e }