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

结果应该是带有 row[1] 值键的散列。yield returnRuby 中不存在,但我确信 Ruby 可以处理这种类型的代码。

4

2 回答 2

4

这就是我理解你在问的问题:“我怎样才能将这样的方法转换为FasterCSV.foreach命令式(通过产生副作用)工作的东西(产生值),以便我可以模块化我的代码”。

答:在 Ruby 中,您可以使用Object#enum_for将each方法转换为Enumerator对象。现在你可以使用你的输出,但我建议使用 Facets 的Enumerable#frequencycount_item_groupsmap

results = FasterCSV.enum_for(:foreach, "file.csv", {}).map do |row|
  row[1].to_s
end.frequency
#=> {"val1"=>3, "val2"=>1}
于 2012-07-03T08:09:30.677 回答
0

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

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

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
于 2012-07-03T01:56:47.740 回答