2012-02-23 52 views
3

我有一个产品文件列出了项目#,产品和价格。我想阅读这个文件并将其初始化为一个散列,项目#是关键,产品和价格是价值。这是我的文件从一个类似CSV的文件创建一个哈希

199, Shoes, 59.99 
211, Shirts, 19.99 
245, Hats, 25.99 
689, Coats, 99.99 
712, Beanies, 6.99 

我希望它看起来像这样。

products = { 
    199 =>['Shoes', 59.99], 
    211 =>['Shirts', 19.99], 
    245 =>['Hats', 25.99], 
    689 => ['Coats', 99.99], 
    712 => ['Beanies', 6.99] 
} 

这就是我所能想出的,它并不是真正想要的。

products_file = File.open("files.txt") 
products_hash = [] 
while ! products_file.eof? 
    product_hash = products_file.gets.chomp 
    print product_hash.split(', ') 
end 

这里是我想出了输出:

["199", "Shoes", "59.99"] 
["211", "Shirts", "19.99"] 
["245", "Hats", "25.99"] 
["689", "Coats", "99.99"] 
["712", "Beanies", "6.99"] 

回答

11

我救了你的数据为CSV文件名为products.csv和这样做:

require 'csv' 
products = {} 
CSV.foreach("products.csv") do |line| 
    products[line[0].to_i] = [line[1].strip, line[2].to_f] 
end 
products 
#=> {199=>["Shoes", 59.99], 211=>["Shirts", 19.99], 245=>["Hats", 25.99], 689=>["Coats", 99.99], 712=>["Beanies", 6.99]} 

结果相同使用each_with_object以更简洁的方式实现,但是它将整个文件一次读入内存,如果文件很大,这可能不是个好主意:

require 'csv' 
products = CSV.read("products.csv").each_with_object({}) do |line, h| 
    h[line[0].to_i] = [line[1].strip, line[2].to_f] 
end 

还有一个功能更强大的方法,因为最初是由Phrogz建议:

require 'csv' 
products = Hash[ CSV.read('products.csv').map do |row| 
    [ row[0].to_i, [row[1].strip,row[2].to_f] ] 
end ] 
+0

+1,伟大的答案。我在这个主题上是一个破纪录,但[我主张'tap' over each_with_object'](http://phrogz.net/tap-vs-each_with_object)。 – Phrogz 2012-02-23 21:59:39

+0

我的'tap'问题是,我更喜欢调用我想要转换的数据的方法,而不是空的集合,这将成为我的结果。不过,我认为这个用例'into',或者'fill_with'是一个很好的别名,可以缓解我的担忧。就个人而言,我总是使用'inject',但发现较新的Rubyists发现'each_with_object'更易于理解。 – 2012-02-23 22:11:27

1

的变化,操纵与CSV的转换器中的数据:

require 'csv' 
products = {} 
CSV.foreach('products.csv', {col_sep: ', ', converters: :numeric}) do |row| 
    products[row.shift] = row 
end 
p products 
#=> {199=>["Shoes", 59.99], 211=>["Shirts", 19.99], 245=>["Hats", 25.99], 689=>["Coats", 99.99], 712=>["Beanies", 6.99]} 
+0

+1,很好的解决方案。我最初的目的是为了简化代码并展示一些Ruby,但我认为你也可以做到这一点。 – 2012-02-24 08:01:21