将CSV文件转换为哈希数组

时间:2022-08-28 21:35:00

I have a csv file, some hockey stats, for example:

我有一个csv文件,一些曲棍球统计数据,例如:

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

I want to save them in an array of hashes. I don't have any headers and I would like to add keys to each value like "time" => "09.09.2008" and so on. Each line should by accessible like arr[i], each value by for example arr[i]["time"]. I prefer CSV class rather than FasterCSV or split. Can you show the way or redirect to some thread where a similar problem was solved?

我想将它们保存在一组哈希中。我没有任何标题,我想为每个值添加键,如“time”=>“09.09.2008”等等。每一行都应该像arr [i]一样可访问,每个值都是例如arr [i] [“time”]。我更喜欢CSV类而不是FasterCSV或拆分。你可以显示方式或重定向到解决类似问题的某个线程吗?

7 个解决方案

#1


27  

You can use the Ruby CSV parser to parse it, and then use Hash[ keys.zip(values) ] to make it a hash.

您可以使用Ruby CSV解析器来解析它,然后使用Hash [keys.zip(values)]使其成为哈希。

Example:

例:

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) ] }

#2


62  

Just pass headers: true

CSV.foreach(data_file, headers: true) do |row|
  puts row.inspect # hash
end

From there, you can manipulate the hash however you like.

从那里,你可以随意操纵哈希。

(Tested with Ruby 2.0, but I think this has worked for quite a while.)

(经过Ruby 2.0测试,但我认为这已经有一段时间了。)

Edit

You say you don't have any headers - could you add a header line to the beginning of the file contents after reading them?

你说你没有任何标题 - 你可以在阅读之后在文件内容的开头添加标题行吗?

#3


24  

This is a fantastic post by Josh Nichols which explains how to do what you're asking.

这是Josh Nichols的精彩文章,解释了如何做你所要求的。

To summarize, here his 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}]

So, you could save the body of your CSV file into a string called body.

因此,您可以将CSV文件的正文保存到名为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"

And then run his code as listed above on it.

然后运行上面列出的代码。

#4


5  

A little shorter solution

一点点解决方案

Parse string:

解析字符串:

CSV.parse(content, headers: :first_row).map(&:to_h)

Parse file:

解析文件:

CSV.open(filename, headers: :first_row).map(&:to_h)

#5


5  

Slight variation on Nathan Long's answer

Nathan Long的回答略有不同

data_file = './sheet.csv'
data = []
CSV.foreach(data_file, headers: true) do |row|
  data << row.to_hash
end

Now data is an array of hashes to do your bidding with!

现在数据是一系列哈希来进行出价!

#6


1  

You can try the following gem also

您也可以尝试以下宝石

require 'csv_hasher'
arr_of_hashes = CSVHasher.hashify('/path/to/csv/file')

The keys of the returned hashes will be the header values of the csv file.

返回的哈希的键将是csv文件的标头值。

If you want to pass your own keys then

如果你想传递自己的密钥

keys = [:key1, :key2, ... ]
arr_of_hashers = CSVHasher.hashify('/path/to/csv/file', { keys: keys }) 

#7


0  

The headers option to the CSV module accepts an array of strings to be used as the headers, when they're not present as the first row in the CSV content.

CSV模块的headers选项接受一个字符串数组,当它们不作为CSV内容的第一行出现时,将用作标题。

CSV.parse(content, headers: %w(time number team_1 team_2 score))

This will generate an enumerable of hashes using the given headers as keys.

这将使用给定标头作为键生成可枚举的哈希值。

#1


27  

You can use the Ruby CSV parser to parse it, and then use Hash[ keys.zip(values) ] to make it a hash.

您可以使用Ruby CSV解析器来解析它,然后使用Hash [keys.zip(values)]使其成为哈希。

Example:

例:

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) ] }

#2


62  

Just pass headers: true

CSV.foreach(data_file, headers: true) do |row|
  puts row.inspect # hash
end

From there, you can manipulate the hash however you like.

从那里,你可以随意操纵哈希。

(Tested with Ruby 2.0, but I think this has worked for quite a while.)

(经过Ruby 2.0测试,但我认为这已经有一段时间了。)

Edit

You say you don't have any headers - could you add a header line to the beginning of the file contents after reading them?

你说你没有任何标题 - 你可以在阅读之后在文件内容的开头添加标题行吗?

#3


24  

This is a fantastic post by Josh Nichols which explains how to do what you're asking.

这是Josh Nichols的精彩文章,解释了如何做你所要求的。

To summarize, here his 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}]

So, you could save the body of your CSV file into a string called body.

因此,您可以将CSV文件的正文保存到名为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"

And then run his code as listed above on it.

然后运行上面列出的代码。

#4


5  

A little shorter solution

一点点解决方案

Parse string:

解析字符串:

CSV.parse(content, headers: :first_row).map(&:to_h)

Parse file:

解析文件:

CSV.open(filename, headers: :first_row).map(&:to_h)

#5


5  

Slight variation on Nathan Long's answer

Nathan Long的回答略有不同

data_file = './sheet.csv'
data = []
CSV.foreach(data_file, headers: true) do |row|
  data << row.to_hash
end

Now data is an array of hashes to do your bidding with!

现在数据是一系列哈希来进行出价!

#6


1  

You can try the following gem also

您也可以尝试以下宝石

require 'csv_hasher'
arr_of_hashes = CSVHasher.hashify('/path/to/csv/file')

The keys of the returned hashes will be the header values of the csv file.

返回的哈希的键将是csv文件的标头值。

If you want to pass your own keys then

如果你想传递自己的密钥

keys = [:key1, :key2, ... ]
arr_of_hashers = CSVHasher.hashify('/path/to/csv/file', { keys: keys }) 

#7


0  

The headers option to the CSV module accepts an array of strings to be used as the headers, when they're not present as the first row in the CSV content.

CSV模块的headers选项接受一个字符串数组,当它们不作为CSV内容的第一行出现时,将用作标题。

CSV.parse(content, headers: %w(time number team_1 team_2 score))

This will generate an enumerable of hashes using the given headers as keys.

这将使用给定标头作为键生成可枚举的哈希值。