Достаточно просто прочитать 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
Хм @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/issues/568