【问题标题】:convert array of hashes to csv file将哈希数组转换为 csv 文件
【发布时间】:2021-04-18 22:23:32
【问题描述】:

如何将散列数组转换为 .csv 文件?

我试过了

    CSV.open("data.csv", "wb") do |csv|
      @data.to_csv
    end

但它是空白的

【问题讨论】:

  • 您有一个变量 (csv) 已设置,但从未被引用。这通常(如您的情况)是错误的指标。

标签: ruby-on-rails csv jruby


【解决方案1】:

试试这个:

CSV.open("data.csv", "wb") do |csv|
  @data.each do |hash|
    csv << hash.values
  end
end

如果您希望 CSV 的第一行包含哈希键(标题行),只需执行以下操作:

CSV.open("data.csv", "wb") do |csv|
  csv << @data.first.keys # adds the attributes name on the first line
  @data.each do |hash|
    csv << hash.values
  end
end

请阅读下面@cgenco 的评论:他为 Array 类写了一个猴子补丁。

【讨论】:

  • 这行得通,但是我也想拥有密钥,这仅列出了值
  • 你想要怎么样?你看过我的第二部分代码吗?您能否发布一个您在哈希数组中拥有的数据的示例以及您希望它如何在 csv 中? @SamanthaKlonaris
  • 另外,你可以直接在 open do 块内csv &lt;&lt; @data.to_csv 试试。
  • 当我添加该行时,我得到 NoMethodError for "csv
  • 我根据这段代码写了一个猴子补丁,所以你可以直接调用array.to_csv(csv_filename):gist.github.com/christiangenco/8acebde2025bf0891987
【解决方案2】:

CSV 足够聪明,可以为您处理非均匀哈希。查看CSV::Writer#<<的代码

所以,这行得通,而且比上面的例子简单一点:

CSV.open("data.csv", "wb", {headers: @data.first.keys} ) do |csv|
  @data.each do |hash|
    csv << hash
  end
end

【讨论】:

  • 赞成比实现,由于某种原因,这不会生成标题
  • headers: 选项只允许您使用&lt;&lt; hash 而不是&lt;&lt; hash.values。如果要包含标题行,仍然需要csv &lt;&lt; @data.first.keys
【解决方案3】:

如果哈希值不统一,那么您最终会得到错误列中的数据。您应该改用 values_at:

CSV.open("data.csv", "wb") do |csv|
  keys = @data.first.keys
  csv << keys
  @data.each do |hash|
    csv << hash.values_at(*keys)
  end
end

【讨论】:

    【解决方案4】:

    如果所有行中的键不同,则当前答案失败。这是最安全的方法:

    data = [{a: 1, b: 2}, {b: 3, c: 4}]
    
    CSV.open("data.csv", "w") { |csv|
      headers = data.flat_map(&:keys).uniq
      csv << headers
      data.each { |row|
        csv << row.values_at(*headers)
      }
    }
    

    所有键都将出现在 CSV 中,即使它们没有出现在第一行:

    a b c
    1 2
    3 4

    【讨论】:

    • 对于我所做的哈希数组data.map(&amp;:keys).flatten.uniq
    • map(&amp;:keys).flattenflat_map(&amp;:keys) 做同样的事情,但后者的性能更高。
    【解决方案5】:

    出于某种原因,没有其他答案对我有用,所以我也会贡献自己的力量。以下是对我使用 ruby​​ 2.7 的哈希数组有用的方法:

    headers = data.map(&:keys).flatten.uniq
    CSV.open("data.csv", "wb", {headers: headers} ) do |csv|
      csv << headers
    
      data.each do |hash|
        csv << hash
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2012-12-21
      • 2011-05-30
      • 2019-10-27
      • 2019-05-23
      • 2012-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      相关资源
      最近更新 更多