所以也许我在 Ruby 中没有得到这个想法,但我有一个关于 Enumerables 注入的问题

发布于 2024-07-28 23:20:38 字数 208 浏览 9 评论 0 原文

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

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

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

The |m,k| thing kind of throws me off. Does this have anything to do with order of precedence?
m standing for 0 (or 1 in some languages) and k for the last in the Array/Hash whatever?

So why do people put a number in .inject()?

Alternatively, is there an easy way to learn how to use this, and exactly what it's value is? Judging from this question I hope you all know I'm pretty noobish to any programming language and Ruby was my first choice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

闻呓 2024-08-04 23:20:38

让我们尝试一个例子。

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 + 数字结尾。 将传递到块的值在两个 | 标记之间命名:prefix_sumnumber

调用的可枚举#inject 的每个值都会作为第二个值依次传递给块。 在此示例中,number 将依次为 3141 >,然后是 5,最后是 9。 所以在这个例子中,该块将被调用六次; 对于 numbers 中的每个位置一次。

传递给块的第一个值(此处名为 prefix_sum)通常称为累加器。 它的初始值,即 #inject 第一次调用该块时使用的值,由传递给 #inject 的参数设置(在本例中,0 )。 该块的返回值确定下一次调用该块的累加器 (prefix_sum) 的值。

当没有更多元素需要处理时,将返回累加器的值(此处存储在 sum 中)。

那么让我们来看看它:

  • #inject 接收 0 和我们的块。
  • #inject 调用我们的块,将 prefix_sum 绑定到 0 (初始累加器值),并将 number 绑定到 3(第一个数组值)。
  • 我们的块将 0+3 计算为 3 并返回它。
  • #inject 调用我们的块,将 prefix_sum 绑定到 3 (返回值),并将 number 绑定到 1 (第二个数组值)
  • 我们的块将 3+1 计算为 4 并返回它。
  • #inject 调用我们的块,将 prefix_sum 绑定到 4 (返回值),并将 number 绑定到 4 (第三个数组值)
  • 我们的块将 4+4 计算为 8 并返回它。
  • #inject 调用我们的块,将 prefix_sum 绑定到 8 (返回值),并将 number 绑定到 1 (第四个数组值)
  • 我们的块将 8+1 计算为 9 并返回它。
  • #inject 调用我们的块,将 prefix_sum 绑定到 9 (返回值),并将 number 绑定到 5 (第五个数组值)
  • 我们的块将 9+5 计算为 14 并返回它。
  • #inject 调用我们的块,将 prefix_sum 绑定到 14 (返回值),并将 number 绑定到 9 (第六个数组值)
  • 我们的块将 14+9 计算为 23 并返回它。
  • 由于不再有数组元素,#inject 返回 23,并且我们将 sum 绑定为该值。

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

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

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

Let's try an example.

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

#inject takes one argument and a block. The block should take two values, and return a new value.

In the above example, the argument to #inject is 0, and the block is do |prefix_sum, number| prefix_sum + number end. The values that will be passed to the block are named in between the two | markers: prefix_sum and number.

Each value of the enumerable #inject was called on is passed as the second value to the block in turn. In this example number will be 3, then 1, then 4, then 1, then 5, then finally 9. So in this example, the block will be invoked six times; once for each position in numbers.

The first value passed to a block (here named prefix_sum) is usually called an accumulator. Its initial value, the value used the first time the block is called by #inject, is set by the argument passed to #inject (in this example, 0). The return value of the block determines the value of the accumulator (prefix_sum) for the next invocation of the block.

When there are no more elements to process, the value of the accumulator is returned (and here stored in sum).

So lets walk through it:

  • #inject receives 0 and our block.
  • #inject invokes our block, binding prefix_sum to 0 (the initial accumulator value) and number to 3 (the first array value).
  • our block calculates 0+3 as 3 and returns it.
  • #inject invokes our block, binding prefix_sum to 3 (the returned value) and number to 1 (the second array value)
  • our block calculates 3+1 as 4 and returns it.
  • #inject invokes our block, binding prefix_sum to 4 (the returned value) and number to 4 (the third array value)
  • our block calculates 4+4 as 8 and returns it.
  • #inject invokes our block, binding prefix_sum to 8 (the returned value) and number to 1 (the fourth array value)
  • our block calculates 8+1 as 9 and returns it.
  • #inject invokes our block, binding prefix_sum to 9 (the returned value) and number to 5 (the fifth array value)
  • our block calculates 9+5 as 14 and returns it.
  • #inject invokes our block, binding prefix_sum to 14 (the returned value) and number to 9 (the sixth array value)
  • our block calculates 14+9 as 23 and returns it.
  • since there are no more array elements, #inject returns 23, and we bind sum to be that value.

You can look at inject as parenthesizing an operation on a list of items, in this example, caluculating:

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

This lets you take any operation which normally only operates on a pair of arguments, and apply it to a list.

聆听风音 2024-08-04 23:20:38

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

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

按照 kjfletch 链接中描述的方式查看它会更简单,细分一个inject(),它们被命名为“result”和“element”。

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

You seem to be confusing block arguments with method arguments.

The number people pass into the inject() method is a method argument that determines the initial value for "m" when you use |m,k| for the block. I don't know where you saw them named m and k, or why they were named so, but it's certainly not because they stand for the first and last element.

It would be simpler to look at it in the way described in kjfletch's link, breakdown of an inject(), where they're named "result" and "element" instead.

The value in using inject() is the ability to be concise. Anything you want to do with inject() could also be done with a call to the each() method, with a much longer block, and extra variable declarations. See this question and the answer to get a feeling for it.

各空 2024-08-04 23:20:38

如果您想了解 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

If you want to find out what any method does in Ruby, you can use the bundled ri tool (so you could type "ri Enumerable.inject" to look up the docs) or search Ruby-Doc. In this case, you would see:

Combines the elements of enum by applying the block to an accumulator value (memo) and each element in turn. At each step, memo is set to the value returned by the block. The first form lets you supply an initial value for memo. The second form uses the first element of the collection as a the initial value (and skips that element while iterating).

# 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
拥抱影子 2024-08-04 23:20:38

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

请参阅此处 块和产量

请参阅此处的 inject() 调用的详细信息。

The |x,y| are used when using blocks. When the yield statement is called you tell it to map the calling variables to x and y.

Look here Blocks and Yield

See here for a breakdown of an inject() call.

阪姬 2024-08-04 23:20:38

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

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

我还看到人们使用 a 表示 accumulatore 表示元素,如下所示:

numbers.inject { |a,e| a+e }

For completeness: m usually means memo; k may mean key (often uses in conjunction with v, which means value). So, for example:

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

I've also seen people use a for accumulator and e for element, like this:

numbers.inject { |a,e| a+e }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文