0

我已经定义了一个这样的数组:

ary = [[0,1], [2,3]]

运行以下代码:

ary.reduce(nil) do |a, i, k|
  puts "#{a.inspect} #{i.inspect} #{k.inspect}"
end

在每次迭代中,我希望变量aik分别保存累加器 ( nil) 的值、内部数组的第一个元素和第二个元素,即我希望这个输出:

nil 0 1
nil 2 3

但结果是:

nil [0, 1] nil
nil [2, 3] nil

为什么?我怎样才能达到我想要的结果?

此外,为什么使用以下代码可以map按我的预期工作?

ary.map do |i, k|
  puts "#{i.inspect} #{k.inspect}"
end

# Output
# 0 1
# 2 3

有什么区别?

4

3 回答 3

5

Splat can work for one level. With map, the block parameter is [0, 1] and so on, which can be spalatted into 0 and 1. With inject, the block parameters are nil and [0, 1], which may be assigned to two variables (without splat), but not three. Splat does not work here because they are already splatted (they are two variables). In order to splat [0, 1], you need to do that within the array, which requires a pair of parentheses.

{|a, (i, j)| ...}
于 2013-04-18T14:08:50.890 回答
3

你想这样做:

A.reduce(nil) { |a, (i, j)| p i }

map和的默认行为之间的差异reduce是由于 Ruby 处理接收单个参数的块的特殊方式。在这种情况下(即map),它会为您生成一个数组,但是对于接收多个参数的块(例如reduce),它需要帮助来确定您想要它做什么。

于 2013-04-18T13:24:19.403 回答
2

让我们尝试以下,以更好地理解:

A = [[0,1], [2,3], [4,5], [6,7]]
A.map { |i| print i } #=> [0, 1][2, 3][4, 5][6, 7]

A = [[0,1], [2,3], [4,5], [6,7]]
A.map { |i,j| print i,j ;print " " } #=> 01 23 45 67

这是因为在第二个代码中,每个元素以以下方式发生的内部分配传递到块:

i,j = [0,1]
i,j = [2,3] so on.

在第一个代码中,它的工作方式如下:

i = [0,1]
i = [2,3] so on.

所以Array#map效果很好。现在,在您的情况下,您没有打印j,只有i这样您才能获得单个值。

A = [[0,1], [2,3], [4,5], [6,7]]
A.map { |i,j| print i ;print " " } #=> 0 2 4 6

现在为了更好地了解一下Enum#inject,看看吧A Simple Pattern for Ruby's inject method。和Ruby's inject() and collect()

于 2013-04-18T13:39:51.500 回答