Parse CSV file with header fields as attributes for each line

I would like to parse a CSV file so that each line is treated as an object with a header line being the attribute names in the object. I could write this, but I'm sure he is already there.

Here is my CSV input:

"foo","bar","baz" 1,2,3 "blah",7,"blam" 4,5,6 

The code looks something like this:

 CSV.open('my_file.csv','r') do |csv_obj| puts csv_obj.foo #prints 1 the 1st time, "blah" 2nd time, etc puts csv.bar #prints 2 the first time, 7 the 2nd time, etc end 

With the Ruby CSV module, I believe that I can only access fields by index. I think the code above would be more readable. Any ideas?

+49
ruby parsing csv
Sep 15 '10 at 12:14
source share
5 answers

Using Ruby 1.9 and above, you can get an index object:

 CSV.foreach('my_file.csv', :headers => true) do |row| puts row['foo'] # prints 1 the 1st time, "blah" 2nd time, etc puts row['bar'] # prints 2 the first time, 7 the 2nd time, etc end 

This is not a point syntax, but it’s much more convenient to work with numeric indexes.

As an aside, for Ruby 1.8.x, FasterCSV is what you need to use the above syntax.

+88
Sep 15 '10 at 12:38
source share

Here is an example of symbolic syntax using Ruby 1.9. In the examples below, the code reads a CSV file named data.csv from the Rails db directory.

:headers => true treats the first row as a header instead of a data row. :header_converters => :symbolize then converts each cell in the title bar to a Ruby symbol.

 CSV.foreach("#{Rails.root}/db/data.csv", {:headers => true, :header_converters => :symbol}) do |row| puts "#{row[:foo]},#{row[:bar]},#{row[:baz]}" end 

In Ruby 1.8:

 require 'fastercsv' CSV.foreach("#{Rails.root}/db/data.csv", {:headers => true, :header_converters => :symbol}) do |row| puts "#{row[:foo]},#{row[:bar]},#{row[:baz]}" end 

Based on the CSV provided by Poul (StackOverflow questionnaire), the output from the above code example will be:

 1,2,3 blah,7,blam 4,5,6 

Depending on the characters used in the headers of the CSV file, headers may need to be displayed to see how the CSV (FasterCSV) converts the line headers to characters. You can output an array of headers from CSV.foreach .

 row.headers 
+25
Jan 28 2018-12-18T00:
source share

Although I'm discussing quite late, a few months ago I started "CSV to object mapper" at https://github.com/vicentereig/virgola .

Given your CSV content, matching them with an array of FooBar objects FooBar pretty simple:

 "foo","bar","baz" 1,2,3 "blah",7,"blam" 4,5,6 
 require 'virgola' class FooBar include Virgola attribute :foo attribute :bar attribute :baz end csv = <<CSV "foo","bar","baz" 1,2,3 "blah",7,"blam" 4,5,6 CSV foo_bars = FooBar.parse(csv).all foo_bars.each { |foo_bar| puts foo_bar.foo, foo_bar.bar, foo_bar.baz } 
+2
Jul 27 2018-12-12T00:
source share

Easy to get hash in Ruby 2.3:

 CSV.foreach('my_file.csv', headers: true, header_converters: :symbol) do |row| puts row.to_h[:foo] puts row.to_h[:bar] end 
+1
Jul 08 '16 at 0:44
source share

Since I asked this question with some frequency:

 array_of_hashmaps = CSV.read("path/to/file.csv", headers: true) puts array_of_hashmaps.first["foo"] # 1 

This is an unblocked version when you want to delete the entire file.

0
Apr 28 '17 at 22:24
source share



All Articles