0

|m,k| 事情有点让我失望。这与优先顺序有什么关系吗?m 代表 0(或某些语言中的 1)和 k 代表 Array/Hash 中的最后一个?

那么为什么人们在 .inject() 中输入一个数字呢?

或者,是否有一种简单的方法来学习如何使用它,以及它的价值到底是什么?从这个问题来看,我希望你们都知道我对任何编程语言都非常陌生,而 Ruby 是我的第一选择。

4

5 回答 5

6

让我们尝试一个例子。

numbers = [ 3, 1, 4, 1, 5, 9 ]
sum = numbers.inject(0) do |prefix_sum, number|
  prefix_sum + number
end

#inject接受一个参数和一个块。该块应采用两个值,并返回一个新值。

在上面的例子中,参数#inject0,块是do |prefix_sum, number| prefix_sum + number end。将传递给块的值在两个|标记之间命名:prefix_sumnumber

被调用的可枚举的每个值都#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_sum0(初始累加器值)和number3第一个数组值)。
  • 我们的块计算0+3as3并返回它。
  • #inject调用我们的块,绑定prefix_sum3(返回值)和number1第二个数组值)
  • 我们的块计算3+1as4并返回它。
  • #inject调用我们的块,绑定prefix_sum4(返回值)和number4第三个数组值)
  • 我们的块计算4+4as8并返回它。
  • #inject调用我们的块,绑定prefix_sum8(返回值)和number1第四个数组值)
  • 我们的块计算8+1as9并返回它。
  • #inject调用我们的块,绑定prefix_sum9(返回值)和number5第五个数组值)
  • 我们的块计算9+5as14并返回它。
  • #inject调用我们的块,绑定prefix_sum14(返回值)和number9第六个数组值)
  • 我们的块计算14+9as23并返回它。
  • 因为没有更多的数组元素,#inject返回23,我们绑定sum到那个值。

您可以将注入视为对项目列表进行括号操作,在此示例中,计算:

((((((0 + 3) + 1) + 4) + 1) + 5) + 9)

这使您可以进行通常仅对一对参数进行操作的任何操作,并将其应用于列表。

于 2009-07-24T13:59:04.087 回答
5

您似乎将块参数与方法参数混淆了。

传入inject() 方法的人数是一个方法参数,当你使用|m,k| 时,它决定了“m”的初始值。为块。我不知道你在哪里看到它们命名为 m 和 k,也不知道它们为什么这样命名,但这肯定不是因为它们代表第一个和最后一个元素。

以 kjfletch 的链接中描述的方式查看它会更简单,inject() 的分解,其中它们被命名为“结果”和“元素”。

使用 inject() 的价值在于简洁。任何你想用 inject() 做的事情也可以通过调用 each() 方法来完成,使用更长的块和额外的变量声明。请参阅此问题和答案以了解它。

于 2009-07-24T11:55:43.617 回答
2

如果您想了解任何方法在 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
于 2009-07-24T14:09:17.413 回答
1

|x,y| 在使用块时使用。当调用 yield 语句时,您告诉它将调用变量映射到 x 和 y。

看这里块和产量

有关注入()调用的详细信息,请参见此处。

于 2009-07-24T06:43:37.520 回答
0

为了完整起见:m通常表示memok可能表示(通常与v一起使用,表示)。因此,例如:

stuff.inject({}) { |m,(k,v)| m.merge(k.to_sym => v) }

我还看到人们使用a for accumulatore for element,像这样:

numbers.inject { |a,e| a+e }
于 2009-07-24T18:43:09.937 回答