Досить просто читати файл CSV в масив з Ruby, але я не можу знайти жодної гарної документації щодо того, як записати масив у файл CSV. Хтось може сказати мені, як це зробити?
Я використовую Ruby 1.9.2, якщо це має значення.
Досить просто читати файл CSV в масив з Ruby, але я не можу знайти жодної гарної документації щодо того, як записати масив у файл CSV. Хтось може сказати мені, як це зробити?
Я використовую Ruby 1.9.2, якщо це має значення.
Відповіді:
У файл:
require 'csv'
CSV.open("myfile.csv", "w") do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
До рядка:
require 'csv'
csv_string = CSV.generate do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
Ось поточна документація щодо CSV: http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html
Я звів це лише до одного рядка.
rows = [['a1', 'a2', 'a3'],['b1', 'b2', 'b3', 'b4'], ['c1', 'c2', 'c3'], ... ]
csv_str = rows.inject([]) { |csv, row| csv << CSV.generate_line(row) }.join("")
#=> "a1,a2,a3\nb1,b2,b3\nc1,c2,c3\n"
Виконайте все вищезазначене і збережіть у csv, в одному рядку.
File.open("ss.csv", "w") {|f| f.write(rows.inject([]) { |csv, row| csv << CSV.generate_line(row) }.join(""))}
ПРИМІТКА:
Конвертувати активну базу даних записів у CSV було б щось подібне, я думаю
CSV.open(fn, 'w') do |csv|
csv << Model.column_names
Model.where(query).each do |m|
csv << m.attributes.values
end
end
Hmm @tamouse, ця суть мене дещо плутає, не читаючи джерело csv, але загалом, якщо припустити, що кожен хеш у вашому масиві має однакову кількість k / v пар, і що ключі завжди однакові, в тому ж порядку (тобто якщо ваші дані структуровані), це має робити:
rowid = 0
CSV.open(fn, 'w') do |csv|
hsh_ary.each do |hsh|
rowid += 1
if rowid == 1
csv << hsh.keys# adding header row (column labels)
else
csv << hsh.values
end# of if/else inside hsh
end# of hsh's (rows)
end# of csv open
Якщо ваші дані не структуровані, це, очевидно, не працюватиме
inject
тут, ви дійсно хочете використовувати map
. Крім того, вам не потрібно передавати порожній рядок join
, оскільки це за замовчуванням. Тож ви можете ще більше зменшити це до цього:rows.map(&CSV.method(:generate_line).join
CSV.generate(headers: hsh.first&.keys) { |csv| hsh.each { |e| csv << e } }
генерує еквівалентний CSV.
Якщо когось цікавить, ось кілька одноразових (і примітка про втрату інформації про тип у CSV):
require 'csv'
rows = [[1,2,3],[4,5]] # [[1, 2, 3], [4, 5]]
# To CSV string
csv = rows.map(&:to_csv).join # "1,2,3\n4,5\n"
# ... and back, as String[][]
rows2 = csv.split("\n").map(&:parse_csv) # [["1", "2", "3"], ["4", "5"]]
# File I/O:
filename = '/tmp/vsc.csv'
# Save to file -- answer to your question
IO.write(filename, rows.map(&:to_csv).join)
# Read from file
# rows3 = IO.read(filename).split("\n").map(&:parse_csv)
rows3 = CSV.read(filename)
rows3 == rows2 # true
rows3 == rows # false
Примітка: CSV втрачає всю інформацію про тип, ви можете використовувати JSON для збереження основної інформації про тип або перейти до дослідної YAML (але простіше для редагування людиною), щоб зберегти всю інформацію про тип - наприклад, якщо вам потрібен тип дати, який би став рядки в CSV та JSON.
Спираючись на відповідь @ boulder_ruby, це те, що я шукаю, припускаючи, що us_eco
містить таблицю CSV від мого суті.
CSV.open('outfile.txt','wb', col_sep: "\t") do |csvfile|
csvfile << us_eco.first.keys
us_eco.each do |row|
csvfile << row.values
end
end
Оновлено суть на https://gist.github.com/tamouse/4647196
Я сам борюся з цим. Це моя думка:
https://gist.github.com/2639448 :
require 'csv'
class CSV
def CSV.unparse array
CSV.generate do |csv|
array.each { |i| csv << i }
end
end
end
CSV.unparse [ %w(your array), %w(goes here) ]
[ %w(your array), %w(goes here) ]
не буде виглядати красиво github.com/pry/pry/isissue/568