Parse CSV файл с полями заголовка в качестве атрибутов для каждой строки
Я хотел бы проанализировать CSV файл, чтобы каждая строка обрабатывалась как объект с строкой-заголовком, являющейся именами атрибутов в объекте. Я мог бы написать это, но я уверен, что он уже там.
Вот мой CSV-вход:
"foo","bar","baz"
1,2,3
"blah",7,"blam"
4,5,6
Код выглядит примерно так:
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
С модулем Ruby CSV я считаю, что могу получить доступ только к полям по индексу. Я думаю, что приведенный выше код был бы более читабельным. Любые идеи?
Ответы
Ответ 1
Используя Ruby 1.9 и выше, вы можете получить индексный объект:
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
Это не точечный синтаксис, но гораздо удобнее работать с числовыми индексами.
Как и в сторону, для Ruby 1.8.x FasterCSV - это то, что вам нужно использовать вышеприведенный синтаксис.
Ответ 2
Вот пример символического синтаксиса с использованием Ruby 1.9. В приведенных ниже примерах код считывает CSV файл с именем data.csv из каталога Rails db.
:headers => true
обрабатывает первую строку как заголовок вместо строки данных. :header_converters => :symbolize
затем преобразует каждую ячейку в строке заголовка в символ Ruby.
CSV.foreach("#{Rails.root}/db/data.csv", {:headers => true, :header_converters => :symbol}) do |row|
puts "#{row[:foo]},#{row[:bar]},#{row[:baz]}"
end
В 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
На основе CSV, предоставленного Poul (вопросник StackOverflow), вывод из приведенного выше примера кода будет:
1,2,3
blah,7,blam
4,5,6
В зависимости от символов, используемых в заголовках CSV файла, может потребоваться вывести заголовки, чтобы увидеть, как CSV (FasterCSV) преобразует заголовки строк в символы. Вы можете вывести массив заголовков из CSV.foreach
.
row.headers
Ответ 3
Хотя я довольно поздно обсуждаю, несколько месяцев назад я начал "CSV to object mapper" на https://github.com/vicentereig/virgola.
Учитывая ваше содержимое CSV, сопоставление их с массивом объектов FooBar
довольно просто:
"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 }
Ответ 4
Легко получить хэш в 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
Ответ 5
Поскольку я задал этот вопрос с некоторой частотой:
array_of_hashmaps = CSV.read("path/to/file.csv", headers: true)
puts array_of_hashmaps.first["foo"] # 1
Это неблокированная версия, когда вы хотите удалить весь файл.