从哈希创建CSV

时间:2016-11-28 22:25:28

标签: ruby csv hash

我需要帮助了解如何将哈希内容转储到csv中。我发现以下帖子正是我试图做的,但不幸的是,没有关于如何调用该方法以便它写入文件的示例。

原帖 Smartly converting array of hashes to CSV in ruby

       def to_csv(csv_filename="hash.csv")
         require 'csv'
         # Get all unique keys into an array:
         keys = self.flat_map(&:keys).uniq
         CSV.open(csv_filename, "wb") do |csv|
           csv << keys
           self.each do |hash|
             # fetch values at keys location, inserting null if not found.
             csv << hash.values_at(*keys)
           end
       end   
end

我的哈希数组称为结果,看起来像这样: (注意:某些键的值为零)

[{:name =>"Mike", :job = "Teacher", :status = "single"},
{:name=> "Joe", :job =>nil, :status = "married"},
{:name =>"Sally", :job = "Nurse", :status = "single"}]

我想将结果哈希的全部内容转储到CSV文件中以便进一步操作。我的问题是我无法弄清楚如何将结果导入csv文件。我跑的时候:

results.to_csv

没有任何反应,也没有创建文件。我想我可能不得不首先播种一个空白文件,但即使这样,也没有内容进入该文件。

有人可以帮助我理解我做错了什么以及为什么这不起作用。提前感谢您的任何帮助。

2 个答案:

答案 0 :(得分:3)

您需要将此方法定义为类Array的实例方法。

class Array
  def to_csv(csv_filename="hash.csv")
    require 'csv'
    # Get all unique keys into an array:
    keys = self.flat_map(&:keys).uniq
    CSV.open(csv_filename, "wb") do |csv|
      csv << keys
      self.each do |hash|
        # fetch values at keys location, inserting null if not found.
        csv << hash.values_at(*keys)
      end
    end   
  end
end

[{ :a=>1, :b=>2 }, { :c=>3 }].to_csv
  #=> [{:a=>1, :b=>2}, {:c=>3}] 

让我们看看写的是什么。

CSV.read("hash.csv")
  #=> [["a", "b", "c"], ["1", "2", nil], [nil, nil, "3"]] 

我推断这是一个来自代码片段的数组方法

self.flat_map(&:keys)

由于映射是键,它表明reiceiver是一个哈希数组。(该表达式可能已经写成flat_map(&:keys)。)

此方法似乎不符合您的要求。

您可以这样保存键和值:

CSV.open("hash.csv", "wb") do |csv|
  arr.each do |h|
    csv << h
  end
end
  #=> [["a", "b", "c"], [1, 2, 3], [4, 5, 6]]

CSV.read("hash.csv")
  #=> [["a", "b", "c"], [1, 2, 3], [4, 5, 6]]

答案 1 :(得分:0)

尝试:

require 'csv'

  def to_csv(csv_filename="hash.csv")
    a = [{:name =>"Mike", :job => "Teacher", :status => "single"},
    {:name=> "Joe", :job =>nil, :status => "married"},
    {:name =>"Sally", :job => "Nurse", :status => "single"}]
    values = a.map do |h|
      h.sort.to_h.values
    end

    CSV.open(csv_filename, "wb") do |csv|
      values.each do |row|
        csv << row
      end
    end
  end

修改

注意:这适用于您的情况,其中所有列都在哈希数组中。例如,您使用值为:job的{​​{1}} jave“Joe”。如果不是这种情况,使用nil是最佳选择