2013-04-18 14 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()