2013-04-18 15 views
0

我已经定义的阵列是这样的:啪块参数

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

运行以下代码:

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

在每次迭代中,我期望变量ai ,和k分别保存累加器(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 

有什么区别?

回答

5

Splat可以工作一个级别。使用map,块参数为[0, 1]等等,可以将其划分为01。用inject,块参数是nil[0, 1],它们可以被分配给两个变量(没有splat),但不是三个。 Splat在这里不起作用,因为它们已经被划掉(它们是两个变量)。为了图示[0, 1],您需要在数组内执行该操作,这需要一对括号。

{|a, (i, j)| ...} 
3

你想这样做:

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

mapreduce默认行为之间的差异是由于特殊的方式处理红宝石接收一个参数块。在这种情况下(即map),它会为您产生一个阵列,但对于接收多个参数的块(如reduce),它需要帮助来确定您希望它执行的操作。

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 WO很好。现在在你的情况下,你没有打印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()