【问题标题】:How to save a hash into a CSV如何将哈希保存到 CSV
【发布时间】:2012-01-01 07:01:48
【问题描述】:

我是 ruby​​ 新手,所以请见谅。

我有一个包含两列的 CSV。一种用于动物名称,一种用于动物类型。 我有一个哈希,所有键都是动物名称,值是动物类型。我想在不使用 fastCSV 的情况下将哈希写入 CSV。我已经想到了几个最简单的想法。这是基本布局。

require "csv"

def write_file
  h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }

  CSV.open("data.csv", "wb") do |csv|
    csv << [???????????]
  end
end

当我打开文件进行读取时,我打开了它File.open("blabla.csv", headers: true) 是否可以以相同的方式写回文件?

【问题讨论】:

  • 你知道,Ruby 1.9 用 FasterCSV 替换了旧的 CSV 模块,所以你实际上是在使用 FasterCSV。因为它是标准库的一部分,所以它被称为 CSV 而不是 FasterCSV。

标签: ruby csv hash append


【解决方案1】:

试试这个:

require 'csv'
h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }
CSV.open("data.csv", "wb") {|csv| h.to_a.each {|elem| csv << elem} }

结果:

1.9.2-p290:~$ cat data.csv 
dog,canine
cat,feline
donkey,asinine

【讨论】:

  • 是的,就是这个主意。将其转换回数组.. 非常酷,谢谢!并使用积木加5分!!击掌! :)
【解决方案2】:

如果你想要列标题并且你有多个哈希:

require 'csv'
hashes = [{'a' => 'aaaa', 'b' => 'bbbb'}]
column_names = hashes.first.keys
s=CSV.generate do |csv|
  csv << column_names
  hashes.each do |x|
    csv << x.values
  end
end
File.write('the_file.csv', s)

(在 Ruby 1.9.3-p429 上测试)

【讨论】:

  • 没有其他答案对我有用,以便保存列标题。这个答案很好用
  • 如果您不想实际输出到磁盘上的文件,CSV.generate 非常方便。
  • 随着行数的增加,生成性能与文件写入的比较如何?
【解决方案3】:

我认为最简单的解决方案是:

def write_file
  h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }

  CSV.open("data.csv", "w", headers: h.keys) do |csv|
    csv << h.values
  end
end

使用多个散列共享相同的键

def write_file
  hashes = [ { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' },
             { 'dog' => 'rover', 'cat' => 'kitty', 'donkey' => 'ass' } ]

  CSV.open("data.csv", "w", headers: hashes.first.keys) do |csv|
    hashes.each do |h|
      csv << h.values
    end
  end
end

【讨论】:

  • ruby v2.5.3 中,至少在 `CSV.open 中需要 write_headers: true
【解决方案4】:

我在这里尝试了解决方案,但得到了不正确的结果(错误列中的值),因为我的源是一个 LDIF 文件,它并不总是包含一个键的所有值。我最终使用了以下内容。

首先,在构建散列时,我会记住一个单独数组中的键,我使用尚未存在的键扩展该数组。

# building up the array of hashes
File.read(ARGV[0]).each_line do |lijn|
    case
    when lijn[0..2] == "dn:" # new record
        record = {}
    when lijn.chomp == '' # end record
        if record['telephonenumber'] # valid record ?
            hashes << record
            keys = keys.concat(record.keys).uniq
        end
    when ...
    end
end

这里重要的一行是keys = keys.concat(record.keys).uniq,它会在找到新键(标题)时扩展键数组。

现在最重要的是:将我们的哈希值转换为 CSV

CSV.open("export.csv", "w", {headers: keys, col_sep: ";"}) do |row|
  row << keys # add the headers
  hashes.each do |hash|
    row << hash # the whole hash, not just the array of values
  end
end

【讨论】:

    【解决方案5】:

    试试这个:

    require 'csv'
    data = { 'one' => '1', 'two' => '2', 'three' => '3' }
    
    CSV.open("data.csv", "a+") do |csv|
            csv << data.keys
            csv << data.values
    end
    

    【讨论】:

      【解决方案6】:

      CSV 可以按任何顺序获取哈希,排除元素,并省略不在HEADERS 中的参数

      require "csv"
      HEADERS = [
        'dog',
        'cat',
        'donkey'
      ]
      
      def write_file
      
        CSV.open("data.csv", "wb", :headers => HEADERS, :write_headers => true) do |csv|
          csv << { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }
          csv << { 'dog' => 'canine'}
          csv << { 'cat' => 'feline', 'dog' => 'canine', 'donkey' => 'asinine' }
          csv << { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine', 'header not provided in the options to #open' => 'not included in output' }
        end
      end
      
      write_file # => 
      # dog,cat,donkey
      # canine,feline,asinine
      # canine,,
      # canine,feline,asinine
      # canine,feline,asinine
      

      这使得使用 CSV 类更加灵活和可读。

      【讨论】:

        【解决方案7】:

        让我们有一个哈希,

        hash_1 = {1=>{:rev=>400, :d_odr=>3}, 2=>{:rev=>4003, :d_price=>300}}
        

        上面的 hash_1 具有一些 id 1,2,.. 的键,而这些值的值再次使用一些键作为 (:rev, :d_odr, :d_price) 进行散列。 假设我们想要一个带有标题的 CSV 文件,

        headers = ['Designer_id','Revenue','Discount_price','Impression','Designer ODR']
        

        然后为 hash_1 的每个值创建一个新数组并插入到 CSV 文件中,

        CSV.open("design_performance_data_temp.csv", "w") do |csv|
         csv << headers
         csv_data = []
         result.each do |design_data|
          csv_data << design_data.first
          csv_data << design_data.second[:rev] || 0
          csv_data << design_data.second[:d_price] || 0
          csv_data << design_data.second[:imp] || 0
          csv_data << design_data.second[:d_odr] || 0
          csv << csv_data
          csv_data = []
         end
        end
        

        现在您已将 design_performance_data_temp.csv 文件保存在相应目录中。 上面的代码可以进一步优化。

        【讨论】:

          【解决方案8】:

          [注意]此线程中的所有答案都假设散列中定义的键的顺序在所有行中都是恒定的。

          为了防止某些值被分配给 csv 中的错误键的问题(我现在面临)(例如:)

          hahes = [
              {:cola => "hello", :colb => "bye"},
              {:colb => "bye", :cola => "hello"}
          ]
          

          使用此线程上大多数答案(包括最佳答案)中的代码生成下表:

          cola  | colb
          -------------
          hello | bye
          -------------
          bye   | hello
          

          你应该这样做:

          require "csv"
          
          csv_rows = [
              {:cola => "hello", :colb => "bye"},
              {:colb => "bye", :cola => "hello"}
          ]
          
          column_names = csv_rows.first.keys
          
          s=CSV.generate do |csv|
            csv << column_names
            csv_rows.each do |row|
              csv << column_names.map{|column_name| row[column_name]} #To be explicit
            end
          end
          
          

          【讨论】:

            猜你喜欢
            • 2012-04-20
            • 1970-01-01
            • 2014-08-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-26
            • 1970-01-01
            相关资源
            最近更新 更多