web-dev-qa-db-fra.com

Tableau de sortie au format CSV dans Ruby

Il est assez facile de lire un fichier CSV dans un tableau avec Ruby, mais je ne trouve aucune bonne documentation sur la façon d'écrire un tableau dans un fichier CSV. Quelqu'un peut-il me dire comment faire cela?

J'utilise Ruby 1.9.2 si cela compte.

168
Jason Swett

Vers un fichier:

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

À une chaîne:

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

Voici la documentation actuelle sur CSV: http://Ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html

297
Dylan Markow

Je n'ai que cela sur une seule ligne.

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" 

Faites tout ce qui précède et enregistrez sur un csv, sur une ligne.

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

REMARQUE:

Convertir une base de données d'enregistrements actifs en CSV serait quelque chose comme ceci, je pense

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

Hmm @tamouse, ce Gist est un peu déroutant pour moi sans lire le code source csv, mais de manière générique, en supposant que chaque hachage de votre tableau a le même nombre de paires k/v & que les clés sont toujours les mêmes, dans le même ordre (c'est-à-dire si vos données sont structurées), cela devrait faire l'acte:

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 vos données ne sont pas structurées, cela ne fonctionnera évidemment pas

33
boulder_ruby

Si vous avez un tableau de tableaux de données:

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

Ensuite, vous pouvez écrire ceci dans un fichier avec les éléments suivants, ce qui est beaucoup plus simple à mon avis:

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

Si vous êtes intéressé, voici quelques réponses uniques (et une note sur la perte d'informations de type dans le format 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

Remarque: le format CSV perd toutes les informations de type. Vous pouvez utiliser JSON pour conserver les informations de type de base ou accéder à YAML verbeux (mais plus facilement modifiable par l'homme) pour conserver toutes les informations de type, par exemple si vous avez besoin d'un type de date qui deviendrait chaînes en CSV et JSON.

19
Kanat Bolazar

En me basant sur la réponse de @ boulder_Ruby, voici ce que je recherche, en supposant que us_eco contient la table CSV de mon Gist.

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

Mis à jour le Gist à l'adresse https://Gist.github.com/tamouse/4647196

9
tamouse

Luttant avec cela moi-même. Ceci est ma prise:

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) ]
2
Felix Rabe