2012-11-12 131 views
3

我無法理解Ruby中的枚舉器。Ruby中的枚舉器

請糾正我如果我錯了,o.enum_for(:arg)方法應該將對象轉換爲枚舉器,每次迭代對象o應該調用arg方法? 什麼困惑我的是這行代碼是如何工作的

[4, 1, 2, 0].enum_for(:count).each_with_index do |elem, index| 
    elem == index 
end 

應該算多少元素是等於其在數組中的位置,以及它的工作原理。但是,我不明白實際發生了什麼。在每次迭代中調用count方法是否爲each_with_index?如果有人能解釋,那會很好。

+0

實際上不是,block被執行4次,只是在irb中測試它 – Zed

回答

0

array.count通常可以佔用一個block,但是它本身會返回一個fixnum,所以它不能鏈接到.with_index其他迭代器可以使用的方式(嘗試array.map.with_index {|x,i ... }等)。

.enum_for(:count)將它轉換爲一個枚舉器,它允許鏈接發生。它對數組的成員進行一次迭代,並保持其數量與其索引相等的數量。所以count只是被調用一次,但是隻有在將數組轉換爲更靈活的數據之後。

3

從編程紅寶石:

計數enum.count {| obj |塊}→int

返回enum中等於obj或 塊返回true值的對象的計數。

因此,如果塊返回true,枚舉器訪問每個元素並將計數加1,在這種情況下,這意味着元素是否等於數組索引。

我還沒有看到大量使用(如果有的話)-I會更傾向於這種模式:

[4, 1, 2, 0].each_with_index.select { |elem, index| elem == index }.count 

編輯

讓我們來看看從示例您的評論:

[4, 1, 2, 0].enum_for(:each_slice, 2).map do |a, b| 
    a + b 
end 

each_slice(2)一次獲取數組2個元素並返回納秒每個切片的數組:

[4, 1, 2, 0].each_slice(2).map # => [[4,1], [2,0]] 

該結果主叫map讓我們每個子陣列上操作,它通入塊:

[4, 1, 2, 0].enum_for(:each_slice, 2).map do |a,b| 
    puts "#{a.inspect} #{b.inspect}" 
end 

導致

4 1 
2 0 

ab憑藉「splatted」塊參數來獲取它們的值:

a, b = *[4, 1] 
a # => 4 
b # => 1 

你也可以把陣列片作爲參數來代替:

[4, 1, 2, 0].enum_for(:each_slice, 2).map {|a| puts "#{a.inspect}"} 

[4, 1] 
[2, 0] 

它可以讓你做到這一點:

[4, 1, 2, 0].enum_for(:each_slice, 2).map {|a| a.inject(:+) } #=> [5,2] 

或者,如果你有的ActiveSupport(即一個Rails應用程序),

[4, 1, 2, 0].enum_for(:each_slice, 2).map {|a| a.sum } 

這似乎比原來的例子更清晰。

+0

真正讓我困惑的是從哪裏| elemen,index |得到它們的值。在我的第一個例子中,它是從我猜each_with_index,但看看這個代碼[4,1,2,0] .enum_for(:each_slice,2).map do | a,b | a + b end,here,| a,b |從each_slice中獲得... – Zed

+0

請參閱我的編輯以獲取更多參與的解釋 – zetetic