J'ai un fichier csv, quelques statistiques de hockey, par exemple:
09.09.2008,1,HC Vitkovice Steel,BK Mlada Boleslav,1:0 (PP)
09.09.2008,1,HC Lasselsberger Plzen,RI OKNA ZLIN,6:2
09.09.2008,1,HC Litvinov,HC Sparta Praha,3:5
Je veux les enregistrer dans un tableau de hachages. Je n'ai pas d'en-tête et je voudrais ajouter des clés à chaque valeur comme "time" => "09.09.2008"
etc. Chaque ligne doit être accessible comme arr[i]
, chaque valeur par exemple arr[i]["time"]
. Je préfère la classe CSV
plutôt que FasterCSV
ou split
. Pouvez-vous montrer le chemin ou rediriger vers un fil où un problème similaire a été résolu?
Vous pouvez utiliser le analyseur Ruby CSV pour l'analyser, puis utiliser Hash[ keys.Zip(values) ]
pour en faire un hachage.
Exemple:
test = '''
09.09.2008,1,HC Vitkovice Steel,BK Mlada Boleslav,1:0 (PP)
09.09.2008,1,HC Lasselsberger Plzen,RI OKNA ZLIN,6:2
09.09.2008,1,HC Litvinov,HC Sparta Praha,3:5
'''.strip
keys = ['time', etc... ]
CSV.parse(test).map {|a| Hash[ keys.Zip(a) ] }
headers: true
CSV.foreach(data_file, headers: true) do |row|
puts row.inspect # hash
end
De là, vous pouvez manipuler le hachage comme vous le souhaitez.
(Testé avec Ruby 2.0, mais je pense que cela a fonctionné pendant un bon moment.)
Vous dites que vous n'avez aucun en-tête - pourriez-vous ajouter une ligne d'en-tête au début du contenu du fichier après les avoir lus?
Ceci est un article fantastique de Josh Nichols qui explique comment faire ce que vous demandez.
Pour résumer, voici son code:
csv = CSV.new(body, :headers => true, :header_converters => :symbol, :converters => [:all, :blank_to_nil])
csv.to_a.map {|row| row.to_hash }
=> [{:year=>1997, :make=>"Ford", :model=>"E350", :description=>"ac, abs, moon", :price=>3000.0}, {:year=>1999, :make=>"Chevy", :model=>"Venture \"Extended Edition\"", :description=>nil, :price=>4900.0}, {:year=>1999, :make=>"Chevy", :model=>"Venture \"Extended Edition, Very Large\"", :description=>nil, :price=>5000.0}, {:year=>1996, :make=>"Jeep", :model=>"Grand Cherokee", :description=>"MUST SELL!\nair, moon roof, loaded", :price=>4799.0}]
Vous pouvez donc enregistrer le corps de votre fichier CSV dans une chaîne appelée body
.
body = "09.09.2008,1,HC Vitkovice Steel,BK Mlada Boleslav,1:0 (PP)
09.09.2008,1,HC Lasselsberger Plzen,RI OKNA ZLIN,6:2
09.09.2008,1,HC Litvinov,HC Sparta Praha,3:5"
Et puis exécutez son code comme indiqué ci-dessus.
Une solution un peu plus courte
Analyser la chaîne:
CSV.parse(content, headers: :first_row).map(&:to_h)
Fichier d'analyse:
CSV.open(filename, headers: :first_row).map(&:to_h)
Légère variation sur Nathan Long réponse
data_file = './sheet.csv'
data = []
CSV.foreach(data_file, headers: true) do |row|
data << row.to_hash
end
Maintenant, data
est un tableau de hachages avec lequel faire vos enchères!
L'option headers
du module CSV accepte un tableau de chaînes à utiliser comme en-têtes, lorsqu'elles ne sont pas présentes comme première ligne dans le contenu CSV.
CSV.parse(content, headers: %w(time number team_1 team_2 score))
Cela générera un énumérable de hachages en utilisant les en-têtes donnés comme clés.
Vous pouvez également essayer le joyau suivant
require 'csv_hasher'
arr_of_hashes = CSVHasher.hashify('/path/to/csv/file')
Les clés des hachages retournés seront les valeurs d'en-tête du fichier csv.
Si vous voulez passer vos propres clés,
keys = [:key1, :key2, ... ]
arr_of_hashers = CSVHasher.hashify('/path/to/csv/file', { keys: keys })