Ruby 枚举器链接 [英] Ruby enumerator chaining

查看:56
本文介绍了Ruby 枚举器链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这个例子中,

[1, 2, 3].each_with_index.map{|i, j| i * j}
# => [0, 2, 6]

我的理解是,由于 each_with_index 枚举器链接到 mapmap 的行为类似于 each_with_index 通过传递块内的索引,并返回一个新数组.

my understanding is that, since each_with_index enumerator is chained to map, map behaves like each_with_index by passing an index inside the block, and returns a new array.

为此,

[1, 2, 3].map.each_with_index{|i, j| i * j}
# => [0, 2, 6] 

我不知道如何解释它.

在这个例子中,

[1, 2, 3, 4].map.find {|i| i == 2}
# => 2

我期望输出为 [2],假设 map 链接到 findmap 将返回一个新数组.

I was expecting the the output to be [2], assuming that map is chained to find, and map would return a new array.

另外,我看到这个:

[1, 2, 3, 4].find.each_with_object([]){|i, j| j.push(i)}
# => [1]

[1, 2, 3, 4].each_with_object([]).find{|i, j| i == 3}
# => [3, []]

你能告诉我如何解释和理解 Ruby 中的枚举器链吗?

Can you let me know how to interpret and understand enumerator chains in Ruby?

推荐答案

您可能会发现分解这些表达式并使用 IRB 或 PRY 来查看 Ruby 正在做什么很有用.让我们开始:

You might find it useful to break these expressions down and use IRB or PRY to see what Ruby is doing. Let's start with:

[1,2,3].each_with_index.map { |i,j| i*j }

enum1 = [1,2,3].each_with_index
  #=> #<Enumerator: [1, 2, 3]:each_with_index>

我们可以使用 Enumerable#to_a(或Enumerable#entries)转换enum1 到一个数组,以查看它将传递给下一个枚举器(或传递给一个块,如果有的话):

We can use Enumerable#to_a (or Enumerable#entries) to convert enum1 to an array to see what it will be passing to the next enumerator (or to a block if it had one):

enum1.to_a
  #=> [[1, 0], [2, 1], [3, 2]]

毫不奇怪.但是 enum1 没有块.相反,我们向它发送方法 Enumerable#map:

No surprise there. But enum1 does not have a block. Instead we are sending it the method Enumerable#map:

enum2 = enum1.map
  #=> #<Enumerator: #<Enumerator: [1, 2, 3]:each_with_index>:map>

您可能会认为这是一种复合"枚举器.此枚举器确实有一个块,因此将其转换为数组将确认它将向块中传递与 enum1 相同的元素:

You might think of this as a sort of "compound" enumerator. This enumerator does have a block, so converting it to an array will confirm that it will pass the same elements into the block as enum1 would have:

enum2.to_a
  #=> [[1, 0], [2, 1], [3, 2]]

我们看到数组 [1,0]enum2 传入块的第一个元素.消歧"应用于此数组以将值分配给块变量:

We see that the array [1,0] is the first element enum2 passes into the block. "Disambiguation" is applied to this array to assign the block variables the values:

i => 1
j => 0

也就是说,Ruby 正在设置:

That is, Ruby is setting:

i,j = [1,0]

我们现在可以通过将方法 each 与块一起发送来调用 enum2:

We now can invoke enum2 by sending it the method each with the block:

enum2.each { |i,j| i*j }
  #=> [0, 2, 6]

接下来考虑:

[1,2,3].map.each_with_index { |i,j| i*j }

我们有:

enum3 = [1,2,3].map
  #=> #<Enumerator: [1, 2, 3]:map>
enum3.to_a
  #=> [1, 2, 3]
enum4 = enum3.each_with_index
  #=> #<Enumerator: #<Enumerator: [1, 2, 3]:map>:each_with_index>
enum4.to_a
  #=> [[1, 0], [2, 1], [3, 2]]
enum4.each { |i,j| i*j }
  #=> [0, 2, 6]

由于 enum2enum4 将相同的元素传递到块中,我们看到这只是做同样事情的两种方式.

Since enum2 and enum4 pass the same elements into the block, we see this is just two ways of doing the same thing.

这是第三个等效链:

[1,2,3].map.with_index { |i,j| i*j }

我们有:

enum3 = [1,2,3].map
  #=> #<Enumerator: [1, 2, 3]:map>
enum3.to_a
  #=> [1, 2, 3]
enum5 = enum3.with_index
  #=> #<Enumerator: #<Enumerator: [1, 2, 3]:map>:with_index>
enum5.to_a
  #=> [[1, 0], [2, 1], [3, 2]]
enum5.each { |i,j| i*j }
  #=> [0, 2, 6]

为了更进一步,假设我们有:

To take this one step further, suppose we had:

[1,2,3].select.with_index.with_object({}) { |(i,j),h| ... }

我们有:

enum6 = [1,2,3].select
  #=> #<Enumerator: [1, 2, 3]:select>
enum6.to_a
  #=> [1, 2, 3]
enum7 = enum6.with_index
  #=> #<Enumerator: #<Enumerator: [1, 2, 3]:select>:with_index>
enum7.to_a
  #=> [[1, 0], [2, 1], [3, 2]]
enum8 = enum7.with_object({})
  #=> #<Enumerator: #<Enumerator: #<Enumerator: [1, 2, 3]:
  #     select>:with_index>:with_object({})>
enum8.to_a
  #=> [[[1, 0], {}], [[2, 1], {}], [[3, 2], {}]]

enum8 传入块的第一个元素是数组:

The first element enum8 passes into the block is the array:

(i,j),h = [[1, 0], {}]

然后应用消歧来为块变量赋值:

Disambiguation is then applied to assign values to the block variables:

i => 1
j => 0
h => {}

请注意,enum8 显示了在 enum8.to_a 的三个元素中的每一个中传递的空散列,但这当然只是因为 Ruby 不知道hash 会在第一个元素传入后看起来像.

Note that enum8 shows an empty hash being passed in each of the three elements of enum8.to_a, but of course that's only because Ruby doesn't know what the hash will look like after the first element is passed in.

这篇关于Ruby 枚举器链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆