Как сохранить хэш в CSV
Я новичок в рубине, поэтому, пожалуйста, простите noobishness.
У меня есть CSV с двумя столбцами. Один для названия животных и один для типа животных.
У меня есть хэш со всеми ключами, являющимися именами животных, а значения - животными. Я хотел бы написать хэш в CSV без использования quickCSV. Я подумал о нескольких идеях, что было бы проще всего. Вот основной макет.
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)
Можно ли написать файл обратно так же?
Ответы
Ответ 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
Ответ 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)
Ответ 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
Ответ 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 более гибкой и удобочитаемой.