是否可以使用哈希作为行生成CSV?

时间:2014-12-16 19:50:44

标签: ruby csv

我有很多哈希,比如这个

# note that the key order isn't consistent
data = [
  {foo: 1, bar: 2, baz: 3},
  {foo: 11, baz: 33, bar: 22}
]

我想将其变成CSV

foo,bar,baz
1,2,3
11,22,33

我这样做:

columns = [:foo, :bar, :baz]
csv_string = CSV.generate do |csv|
  csv << columns
  data.each do |d|
    row = []
    columns.each do |column|
      row << d[column]
    end
    csv << row
  end
end

有更好的方法吗?我想做的是像......

csv_string = CSV.generate do |csv|
  csv << [:foo, :bar, :baz]
  data.each do |row|
    csv.add_row_hash row
  end
end

3 个答案:

答案 0 :(得分:2)

通过传递给生成的相应选项,您可以实现您想要的效果。请注意,一旦设置了标题,您就可以将哈希直接添加到CSV中。

c = CSV.generate(:headers => [:foo, :bar, :baz], :write_headers => true) do |csv|
  data.each { |row| csv << row }
end

输出:

foo,bar,baz
1,2,3
11,22,33

答案 1 :(得分:1)

如果密钥丢失,您需要获取所有可能的密钥

keys = data.map(&:keys).flatten.uniq

然后使用这些键映射每一行。

csv_string = CSV.generate do |csv|
  csv << keys
  data.each do |row|
    csv << row.values_at(keys)
  end
end

答案 2 :(得分:-1)

我的第一个想法:您的data可用于将数据插入数据库表。 如果将其与csv-output of a DB-table结合使用,则可以使用其他解决方案。

示例:

data = [
  {foo: 1, bar: 2, baz: 3},
  {foo: 11, baz: 33, bar: 22},
  {foo: 11, baz: 33, bar: 22, xx: 3}, #additional parameters are no problem
]

#Prepare DB as a helper
require 'sequel'
DB = Sequel.sqlite
DB.extension(:sequel_3_dataset_methods) #define to_csv 
DB.create_table(:tab){
  add_column :foo
  add_column :bar
  add_column :baz
}

DB[:tab].multi_insert(data) #fill table
#output as csv (the gsub is necessary on Windows, maybe not necessary on other OS
puts DB[:tab].to_csv.gsub("\r\n","\n")  

缺点:你需要续集

优势:您可以非常轻松地调整订单:

puts DB[:tab].select(:bar, :baz).to_csv.gsub("\r\n","\n")