ruby 将 CSV 文件转换为哈希数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14199784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 05:38:49  来源:igfitidea点击:

Convert CSV file into array of hashes

rubycsvmultidimensional-array

提问by Mythago

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 CSVclass rather than FasterCSVor 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"]。我更喜欢CSVclass 而不是FasterCSVor split。你能指出方法或重定向到解决类似问题的某个线程吗?

采纳答案by AJcodez

You can use the Ruby CSV parserto 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) ] }

回答by Nathan Long

Just pass headers: true

刚刚通过 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?

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

回答by CodeBiker

This is a fantastic postby 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.

然后运行上面列出的他的代码就可以了。

回答by Pavel Evstigneev

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)

回答by lacostenycoder

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 datais an array of hashes to do your bidding with!

现在data是一组散列值供您出价!

回答by Will Madden

The headersoption 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.

headersCSV 模块的选项接受要用作标题的字符串数组,当它们不作为 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.

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

回答by gaurav.singharoy

You can try the following gem also

您也可以尝试以下 gem

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