2016-03-06 67 views
1

我偶然發現了這樣的例子:爲什麼要使用枚舉紅寶石

file = "./path" 
var = Enumerator.new do |y| 
CSV.foreach(file) do |row| 
      y.yield(row) 
    end 
end 

問題是,爲什麼任何種類的存儲數據,內部統計員,insted的陣列?是什麼什麼上面,這之間的行爲差​​異:對於這兩種情況下

file = "./path" 
var = [] 
CSV.foreach(file) do |row| 
    var << row 
end 

時,我想的東西與數據看起來是一樣的:

var.each {|row| puts row} 

那麼有什麼優點和缺點這樣的結構?

回答

4

一般來說,迭代器可用於懶惰地生成一系列對象。 創建惰性枚舉相比創建效率更高的項目集合,這是主要優勢。

例如,如果您的枚舉器循環僅迭代3百萬個項目的前5項,那麼這就是所有收益率回報,並且您沒有在內部首先建立100萬個項目的集合。

所以,你不需要加載所有的3百萬項目只是爲了你的被調用函數可以繼續執行其餘的代碼。

迭代器是返回序列的手段。

有時序列甚至可能是無限

它將懶惰評估的函數式編程概念帶入Ruby--至少對於枚舉來說。

返回一個集合並返回一個集合生成器有很大的區別。

+0

到目前爲止這是真實的,但請注意,懶惰的枚舉器是在稍後添加的。統計員沒有他們就存在。 – sawa

+0

@sawa _lazy enumerator_特性是'Enumerator'和'Enumarable'之間的一個適配器,可以輕鬆支持枚舉類型的懶惰。 – sschmeck

0

看到代碼的區別在循環中添加一個puts

seq = (1..3) 
enum = Enumerator.new do |y| 
    seq.each do |i| 
    puts "Grabbing #{i} with enumerator" 
    y.yield(i) 
    end 
end 
enum.each { |i| puts "Taken #{i} from enumerator" } 

# Grabbing 1 with enumerator 
# Taken 1 from enumerator 
# Grabbing 2 with enumerator 
# Taken 2 from enumerator 
# Grabbing 3 with enumerator 
# Taken 3 from enumerator   

array = [] 
seq.each do |i| 
    puts "Grabbing #{i} with array" 
    array << i 
end 
array.each { |i| puts "Taken #{i} from array" } 

# Grabbing 1 with array  
# Grabbing 2 with array  
# Grabbing 3 with array  
# Taken 1 from array   
# Taken 2 from array   
# Taken 3 from array 

像由塔爾Avissar的Enumerator提到獲取被稱爲懶評價需要的時候它的價值。這種行爲在某些情況下是有益的。

# infinite number sequence 
numbers = Enumerator.new do |y| 
    n = 0       
    loop { y.yield(n += 1) }  
end        
puts numbers.take(3).join(', ') 
# 1, 2, 3 

當處理巨大或無限的序列時,差異是非常重要的。