Анализ файла CSV с полями заголовка в качестве атрибутов для каждой строки - PullRequest
63 голосов
/ 15 сентября 2010

Я хотел бы проанализировать файл 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 я считаю, что могу получить доступ к полям только по индексу.Я думаю, что приведенный выше код будет немного более читабельным.Есть идеи?

Ответы [ 5 ]

110 голосов
/ 15 сентября 2010

Используя 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 - это то, что вам нужно для использования вышеуказанного синтаксиса.

36 голосов
/ 28 января 2012

Вот пример символического синтаксиса с использованием 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
4 голосов
/ 08 июля 2016

Легко получить хэш в 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
2 голосов
/ 27 июля 2012

Хотя я довольно поздно к обсуждению, несколько месяцев назад я начал "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 }
0 голосов
/ 29 апреля 2017

Поскольку я задавал этот вопрос с некоторой частотой:

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

Это неблокируемая версия, когда вы хотите сохранить весь файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...