2012-07-02 49 views
1

鉴于我有类似以下的代码,我需要做些什么才能使它工作?如何创建一个按需求出另一个可枚举对象的可枚举对象?

config = {} #options for faster csv 
input_file = "foo.csv" 

# can be in any class or module 
def count_item_groups(items) 
    results = Hash.new(0) 
    (items || []).each do |current| 
     results[current.to_s] += 1 
    end 
    results 
end 

row_value_iterator = FasterCSV.foreach(input_file, config) do |row| 
    yield return row[1] 
end 

result = count_item_groups(row_value_iterator) 

对战这样的代码

def do_it_all 
    results = Hash.new(0) 
    FasterCSV.foreach(input_file, config) do |row| 
     results[row[1].to_s] += 1 
    end 
    results 
end 

结果应与行[1]的值的密钥的散列。 Ruby中不存在yield return,但我确定Ruby可以处理这种类型的代码。

+0

什么是收益率回归行[1]该怎么办?和什么是C#标签? – oldergod

+0

是的。 http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx我想将所创建的迭代器(row_value_iterator)中的行值逐个1放入到count_item_groups方法中。 – Jason

+0

count_item_groups正在调用.each集合。我想这样做是为了将知道CSV文件中哪些列的代码从将执行分组的代码中分离出来。 – Jason

回答

4

这就是我明白你问:“我怎样才能变换的方法类似FasterCSV.foreach,工程势在必行(做副作用)至一些功能(产生值),所以我可以模块化我的代码“。

答案:在Ruby可以转化每个方法将一个枚举对象与Object#enum_for。现在,您可以与map的输出使用count_item_groups,但我会建议使用构面Enumerable#frequency

results = FasterCSV.enum_for(:foreach, "file.csv", {}).map do |row| 
    row[1].to_s 
end.frequency 
#=> {"val1"=>3, "val2"=>1} 
0

我不确定你在问什么,我认为这与可链式功能有关。

而不是将对象迭代器作为参数传递给另一个迭代器,在ruby中,您可以链接这些迭代器。它mignt看起来像这样。

row_value_iterator = FasterCSV.foreach(input_file, config).map do |row| 
    row[1] 
end 

result = row_value_iterator.each_with_object(Hash.new(0)) do |current,results| 
    results[current.to_s] += 1 
end 

或做它在真正链风格:

result = FasterCSV.foreach(input_file,config).each_with_object(Hash.new(0)) do |row,results| 
    results[row[1].to_s] += 1 
end 
+0

我认为OP想要的是能够将CSV阅读与事件计数分开(这是一个合理的事情)。 – tokland