如何创建一个可枚举的对象,根据需求评估另一个可枚举对象?

时间:2012-07-02 23:45:54

标签: ruby enumeration

鉴于我有以下代码,我需要做些什么才能使其正常工作?

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可以处理这种类型的代码。

2 个答案:

答案 0 :(得分:4)

这就是我理解你所问的问题:“我怎样才能将像FasterCSV.foreach这样的方法转换为必要的(通过副作用)到功能性的东西(产生值),这样我就能模块化我的代码”。

答案:在Ruby中,您可以使用Object#enum_for每个方法转换为 Enumerator 对象。现在,您可以将count_item_groupsmap的输出结合使用,但我建议您使用Facets'Enumerable#frequency

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

答案 1 :(得分: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