合并ruby中的csv数据以获取唯一值的总数/总和

时间:2014-09-26 13:03:44

标签: ruby csv

我还在努力解决基本问题,但我还没有找到在线答案。

我正在获取类似数据的CSV作为名称和数量:

Foo, 1.5
Bar, 1.2
Foo, 1.1
...

并希望将其合并为唯一名称,并将总计作为新值:

Foo, 2.6   #total of both Foo lines
Bar, 1.2
...

每次数据集都不大,但任务非常重复。

我尝试将其转换为哈希数组,找到uniq名称,然后使用inject,但不知怎的,它变得相当复杂并且无效。此外,循环所有内容似乎不是理想的方法。

有没有人有一个我错过的好的简单的想法或解决方案? (我只找到" Extract value from row in csv and sum it"用于PHP。)

3 个答案:

答案 0 :(得分:3)

首先,您可以使用Ruby的CSV库来解析和转换您的CSV数据:

require 'csv'

csv_data = "Foo, 1.5\nBar, 1.2\nFoo, 1.1"

data_array = CSV.parse(csv_data, converters: :numeric)
#=> [["Foo", 1.5], ["Bar", 1.2], ["Foo", 1.1]]

要对值进行求和,我会使用散列和each_with_object

data_array.each_with_object(Hash.new(0)) { |(k, v), h| h[k] += v }
#=> {"Foo"=>2.6, "Bar"=>1.2}

答案 1 :(得分:1)

哈希数组似乎是最简单的方法:

让我们说:

CSV=[["foo",1.5],["bar",2.2],["foo",1.1]]

只是做:

myCSV=[["foo",1.5],["bar",1.2],["foo",1.1]]
myCSV.each_with_object(Hash.new(0.0)){|row,sum| sum[row[0]]+=row[1]}
=> {
  "foo" => 2.6,
  "bar" => 1.2
}

如果您正在阅读文件,使用CSV库或多或少相同:

sum=Hash.new(0.0)
CSV.foreach("path/to/file.csv") do |row|
  sum[row[0]]+=row[1]
end

答案 2 :(得分:1)

为每个项目的第一次出现很好地传递0.0作为哈希帐户的default选项:

input = [ ['Foo', 1.5],
          ['Bar', 1.2],
          ['Foo', 1.1] ]

result = input.inject(Hash.new(0.0)) do |sum, (key, value)|
  sum[key] += value
  sum
end

p result