2012-02-23 72 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