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.
这将使用给定标头作为键生成可枚举的哈希值。