Выходной массив в CSV в Ruby - PullRequest
167 голосов
/ 28 января 2011

Достаточно легко прочитать файл CSV в массив с помощью Ruby, но я не могу найти хорошую документацию о том, как записать массив в файл CSV. Может кто-нибудь сказать мне, как это сделать?

Я использую Ruby 1.9.2, если это имеет значение.

Ответы [ 6 ]

297 голосов
/ 28 января 2011

К файлу:

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

33 голосов
/ 17 июля 2012

У меня это всего одна строка.

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

Если ваши данные не структурированы, это явно не сработает

20 голосов
/ 24 января 2017

Если у вас есть массив массивов данных:

rows = [["a1", "a2", "a3"],["b1", "b2", "b3", "b4"], ["c1", "c2", "c3"]]

Затем вы можете записать это в файл со следующим, что, я думаю, намного проще:

require "csv"
File.write("ss.csv", rows.map(&:to_csv).join)
18 голосов
/ 29 октября 2015

Если кому-то интересно, вот несколько однострочников (и примечание о потере информации о типах в 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.

9 голосов
/ 13 ноября 2013

Основываясь на ответе @ 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

2 голосов
/ 09 мая 2012

Борюсь с этим сам. Это мой дубль:

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) ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...