解析 CSV 文件,将标题字段作为每行的属性

发布于 2024-09-18 22:00:27 字数 443 浏览 5 评论 0原文

我想解析 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 模块,我相信我只能通过索引访问字段。我认为上面的代码会更具可读性。有什么想法吗?

I would like to parse a CSV file so that each row is treated like an object with the header-row being the names of the attributes in the object. I could write this, but I'm sure its already out there.

Here is my CSV input:

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

The code would look 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 Ruby's CSV module I believe I can only access the fields by index. I think the above code would be a bit more readable. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

撩心不撩汉 2024-09-25 22:00:27

使用 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

Using Ruby 1.9 and above, you can get a an indexable 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

It's not dot syntax but it is much nicer to work with than numeric indexes.

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

兔姬 2024-09-25 22:00:27

下面是使用 Ruby 1.9 的符号语法的示例。在下面的示例中,代码从 Rails db 目录读取名为 data.csv 的 CSV 文件。

<代码>:标题=> 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

根据 Poul(StackOverflow 提问者)提供的 CSV,上面示例代码的输出将是:

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

根据 CSV 文件标题中使用的字符,可能需要将标题输出为为了查看 CSV (FasterCSV) 如何将字符串标题转换为符号。您可以从 CSV.foreach 中输出标头数组。

row.headers

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

:headers => true treats the first row as a header instead of a data row. :header_converters => :symbolize parameter then converts each cell in the header row into 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 the Poul (the StackOverflow asker), the output from the example code above will be:

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

Depending on the characters used in the headers of the CSV file, it may be necessary to output the headers in order to see how CSV (FasterCSV) converted the string headers to symbols. You can output the array of headers from within the CSV.foreach.

row.headers
著墨染雨君画夕 2024-09-25 22:00:27

在 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

Easy to get a 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
_蜘蛛 2024-09-25 22:00:27

虽然我很晚才开始讨论,但几个月前我在 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 }

Although I am pretty late to the discussion, a few months ago I started a "CSV to object mapper" at https://github.com/vicentereig/virgola.

Given your CSV contents, mapping them to an array of FooBar objects is pretty straightforward:

"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 }
乖乖兔^ω^ 2024-09-25 22:00:27

因为我经常遇到这个问题:

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

当您想要读取整个文件时,这是非块版本。

Since I hit 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 the non-block version, when you want to slurp the whole file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文