【问题标题】:Creating a CSV from a hash从哈希创建 CSV
【发布时间】:2017-04-12 18:48:18
【问题描述】:

我需要帮助了解如何将我的哈希内容转储到 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

什么都没有发生,没有文件被创建。我想我可能必须先播种一个空白文件,但即便如此,文件中也没有任何内容。

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

【问题讨论】:

  • 请解释“什么都没发生”。如果在运行 results.to_csv 时实际上没有任何反应,那么您的 Ruby 就坏了。出现这种情况的几率非常小。如果您遇到错误,请将其包含在您的问题中。

标签: ruby csv hash


【解决方案1】:

您需要将此方法定义为类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)

由于映射到键,它表明接收者是一个哈希数组。(该表达式可以写成flat_map(&amp;: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]]

【讨论】:

  • @CarySwoverland,那是票。我必须将它包装为 Array 类的实例。有没有办法在不上课的情况下做到这一点?在我看来,将它作为自己的方法会容易得多。另外,我只是想知道为什么它需要在课堂上。再次感谢您的帮助。
  • pjw23,考虑实例方法Array#size。给定一个数组arrarr.size 是数组的大小。您可以在另一个类中编写返回相同值的实例方法,如下所示:def my_arr_size(arr); arr.size; end;也就是说,只需将self 中的self 设为my_arr_size 的参数即可。如果Array 方法有参数和/或块,则包括这些参数,连同arr,以及在另一个类中定义的方法中的块。清楚吗?
【解决方案2】:

试试:

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 和值 nil 生成“Joe”。如果这不是你的情况,使用value_at 是最好的选择

【讨论】:

  • 感谢您的意见。我仍然有同样的问题,它没有将数据写入 hash.csv。当我输入:results.to_csv 时,我可以在屏幕上看到它。为了将数据输出到 csv,我需要做什么?谢谢。
  • 我写的例子在我的电脑上工作,它写入一个 csv 文件。 SV.open(...) do.... csv &lt;&lt; "data" 完成这项工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 2016-10-17
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 2011-11-26
  • 1970-01-01
相关资源
最近更新 更多