Matriz de salida a CSV en Ruby

Es bastante fácil leer un archivo CSV en una matriz con Ruby, pero no puedo encontrar ninguna buena documentación sobre cómo escribir una matriz en un archivo CSV. ¿Puede alguien decirme cómo hacer esto?

Estoy usando Ruby 1.9.2 si eso importa.

A un archivo:

require 'csv' CSV.open("myfile.csv", "w") do |csv| csv < < ["row", "of", "CSV", "data"] csv << ["another", "row"] # ... end 

A una cadena:

 require 'csv' csv_string = CSV.generate do |csv| csv < < ["row", "of", "CSV", "data"] csv << ["another", "row"] # ... end 

Aquí está la documentación actual sobre CSV: http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html

Lo he reducido a una sola línea.

 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" 

Haga todo lo anterior y guárdelo en un csv, en una línea.

 File.open("ss.csv", "w") {|f| f.write(rows.inject([]) { |csv, row| csv < < CSV.generate_line(row) }.join(""))} 

NOTA:

Convertir una base de datos de registros activa a csv sería algo como esto, creo

 CSV.open(fn, 'w') do |csv| csv < < Model.column_names Model.where(query).each do |m| csv << m.attributes.values end end 

Hmm @tause, esa idea es algo confusa para mí sin leer la fuente csv, pero genéricamente, asumiendo que cada hash en tu matriz tiene el mismo número de pares k / v y que las claves son siempre las mismas, en el mismo orden (es decir, si sus datos están estructurados), esto debería hacer la escritura:

 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 

Si sus datos no están estructurados, esto obviamente no funcionará

Si alguien está interesado, aquí hay algunas frases sencillas (y una nota sobre la pérdida de información de tipo en 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 

Nota: CSV pierde toda la información de tipo, puede usar JSON para conservar información de tipo básico o ir a YAML detallado (pero más fácil de editar para los humanos) para conservar toda la información de tipo; por ejemplo, si necesita el tipo de fecha, que se convertiría cadenas en CSV y JSON.

Si tiene una matriz de matrices de datos:

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

Luego puede escribir esto en un archivo con lo siguiente, que creo que es mucho más simple:

 require "csv" File.write("ss.csv", rows.map(&:to_csv).join) 

Sobre la base de la respuesta de @boulder_ruby, esto es lo que estoy buscando, suponiendo que us_eco contiene la tabla CSV a partir de mi esencia.

 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 

Se actualizó la esencia en https://gist.github.com/tamouse/4647196

Luchando con esto yo mismo. Esta es mi opinión:

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) ]