将CSV文件转换为哈希数组

Myt*_*ago 39 ruby csv multidimensional-array

我有一个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
Run Code Online (Sandbox Code Playgroud)

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

Nat*_*ong 71

刚过去 headers: true

CSV.foreach(data_file, headers: true) do |row|
  puts row.inspect # hash
end
Run Code Online (Sandbox Code Playgroud)

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

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

编辑

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

  • 从技术上讲,我认为每一行都是`CSV :: Row`的实例,它的行为类似于`Hash`,但实际上并不继承`Hash`. (3认同)
  • 你也可以使用`CSV.parse(data,headers:true).map(&:to_h)`来达到类似的效果,同时考虑到Jared的注释.这会将您的CSV转换为散列数组,并将标题作为键.您还可以在选项`header_converters :: symbol`中使用符号作为键而不是列名作为字符串. (3认同)

AJc*_*dez 36

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

例:

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) ] }
Run Code Online (Sandbox Code Playgroud)

  • @ user1955522 CSV.parse方法接受字符串作为参数,而不是数组.尝试`CSV.read('data.txt').map {| a | 哈希[keys.zip(a)]}`. (2认同)

Cod*_*ker 29

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

总结一下,这里是他的代码:

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}]
Run Code Online (Sandbox Code Playgroud)

因此,您可以将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"
Run Code Online (Sandbox Code Playgroud)

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

  • 你也可以把它减少到:`CSV.new(body,headers:true).map(&:to_hash)`(至少在Ruby 2.1.5中) (7认同)

Pav*_*eev 19

一点点解决方案

解析字符串:

CSV.parse(content, headers: :first_row).map(&:to_h)
Run Code Online (Sandbox Code Playgroud)

解析文件:

CSV.open(filename, headers: :first_row).map(&:to_h)
Run Code Online (Sandbox Code Playgroud)


lac*_*der 5

内森龙的回答略有不同

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

现在data是一系列哈希来做你的出价!

  • 甚至更精简:`data = CSV.foreach(data_file,headers:true).map {| row | row.to_h}` (2认同)