如何将哈希保存到CSV中

时间:2023-02-15 19:52:39

I am new in ruby so please forgive the noobishness.

我是红宝石的新人,所以请原谅我的无礼。

I have a CSV with two columns. One for animal name and one for animal type. I have a hash with all the keys being animal names and the values being animal type. I would like to write the hash to the CSV without using fasterCSV. I have thought of several ideas what would be easiest.. here is the basic layout.

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

require "csv"

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

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

When I opened the file to read from it I opened it File.open("blabla.csv", headers: true) Would it be possible to write back to the file the same way?

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

7 个解决方案

#1


40  

Try this:

尝试这个:

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

Will result:

将导致:

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

#2


51  

If you want column headers and you have multiple hashes:

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

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)

(tested on Ruby 1.9.3-p429)

(在Ruby 1.9.3-p429上测试)

#3


23  

I think the simplest solution to your original question:

我认为原始问题的最简单的解决方案:

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

With multiple hashes that all share the same keys:

使用多个哈希,它们共享相同的键:

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

#4


4  

CSV can take a hash in any order, exclude elements, and omit a params not in the HEADERS

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

This makes working with the CSV class more flexible and readable.

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

#5


1  

I tried the solutions here but got an incorrect result (values in wrong columns) since my source is a LDIF file that not always has all the values for a key. I ended up using the following.

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

First, when building up the hash I remember the keys in a separate array which I extend with the keys that are not allready there.

首先,在构建哈希时,我记得单独数组中的键,我使用那些尚未存在的键扩展。

# 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

The important line here is keys = keys.concat(record.keys).uniq which extends the array of keys when new keys (headers) are found.

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

Now the most important: converting our hashes to a CSV

现在最重要的是:将我们的哈希值转换为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

#6


1  

Try this:

尝试这个:

require 'csv'
data = { 'one' => '1', 'two' => '2', 'three' => '3' }

CSV.open("data.csv", "a+") do |csv|
        csv << data.keys
        csv << data.values
end

#7


0  

Lets we have a hash,

让我们有一个哈希,

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

The above hash_1 having keys as some id 1,2,.. and values to those are again hash with some keys as (:rev, :d_odr, :d_price). Suppose we want a CSV file with headers,

上面的hash_1将键作为某些id 1,2,..和值的值再次哈希,其中一些键为(:rev,:d_odr,:d_price)。假设我们想要一个包含标题的CSV文件,

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

Then make a new array for each value of hash_1 and insert it in CSV file,

然后为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

Now you are having design_performance_data_temp.csv file saved in your corresponding directory. Above code can further be optimized.

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

#1


40  

Try this:

尝试这个:

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

Will result:

将导致:

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

#2


51  

If you want column headers and you have multiple hashes:

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

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)

(tested on Ruby 1.9.3-p429)

(在Ruby 1.9.3-p429上测试)

#3


23  

I think the simplest solution to your original question:

我认为原始问题的最简单的解决方案:

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

With multiple hashes that all share the same keys:

使用多个哈希,它们共享相同的键:

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

#4


4  

CSV can take a hash in any order, exclude elements, and omit a params not in the HEADERS

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

This makes working with the CSV class more flexible and readable.

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

#5


1  

I tried the solutions here but got an incorrect result (values in wrong columns) since my source is a LDIF file that not always has all the values for a key. I ended up using the following.

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

First, when building up the hash I remember the keys in a separate array which I extend with the keys that are not allready there.

首先,在构建哈希时,我记得单独数组中的键,我使用那些尚未存在的键扩展。

# 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

The important line here is keys = keys.concat(record.keys).uniq which extends the array of keys when new keys (headers) are found.

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

Now the most important: converting our hashes to a CSV

现在最重要的是:将我们的哈希值转换为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

#6


1  

Try this:

尝试这个:

require 'csv'
data = { 'one' => '1', 'two' => '2', 'three' => '3' }

CSV.open("data.csv", "a+") do |csv|
        csv << data.keys
        csv << data.values
end

#7


0  

Lets we have a hash,

让我们有一个哈希,

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

The above hash_1 having keys as some id 1,2,.. and values to those are again hash with some keys as (:rev, :d_odr, :d_price). Suppose we want a CSV file with headers,

上面的hash_1将键作为某些id 1,2,..和值的值再次哈希,其中一些键为(:rev,:d_odr,:d_price)。假设我们想要一个包含标题的CSV文件,

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

Then make a new array for each value of hash_1 and insert it in CSV file,

然后为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

Now you are having design_performance_data_temp.csv file saved in your corresponding directory. Above code can further be optimized.

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