如何通过在 Ruby 中循环子数组来创建键值对?

问题描述 投票:0回答:1

我正在尝试编写一个 Ruby 程序,它将解析以下 TSV 文件并循环遍历每条记录,将每个 shop 名称(最后一列)添加为哈希中的键,并将关联的 price (第二列)添加为每个对应键的值:

White Bread £1.20   Baker
Whole Milk  £0.80   Corner Shop
Gorgonzola  £10.20  Cheese Shop
Mature Cheddar  £5.20   Cheese Shop
Limburger   £6.35   Cheese Shop
Newspaper   £1.20   Corner Shop
Ilchester   £3.99   Cheese Shop

因此,我们的目标是最终得到一个包含以下格式条目的哈希:shop => price

这是我到目前为止得到的代码:

totals = {}

File.open("shopping.tsv") do |file|
  records = file.each_line.map { |line| line.chomp.split("\t") }
  records.each { |_, price, shop| totals[shop.to_sym] = price }
  puts(totals) 
 end

这会产生不正确的输出,仅解析部分记录并将其添加到 totals 哈希中(并且关键符号的呈现方式也存在一些不一致):

{:Baker=>"£1.20", :"Corner Shop"=>"£1.20", :"Cheese Shop"=>"£3.99"}

为什么会发生这种情况?上面的输出以所需的格式提供了数据,但缺少大部分记录。我最终想扩展这个程序,通过仅在给定的键不存在的情况下添加新的哈希条目来提供每个商店的总计,但我想在进一步讨论之前先弄清楚这个问题的真相。

我在打印调试上花费了相当多的时间,并且可以确认数据正在被 file.each_line.map 方法正确解析,每条记录都被转换为包含预期字段的子数组。问题似乎源于下一行,它尝试仅将商店和价格字段添加到哈希中。

我还检查了 Stack Overflow,并注意到类似的错误输出通常源于在更改数组时尝试迭代数组,尽管这似乎不是我在这里尝试做的事情(如果我这样做,请纠正我)我错了)。我还尝试使用 duplicate 方法创建每个子数组的副本,而不是尝试从原始数据创建哈希,但仍然得到相同的结果。

如果有人能告诉我这里发生了什么,我将不胜感激。

提前致谢。

ruby data-structures hash text-files sub-array
1个回答
0
投票

我现在意识到您正在尝试计算每个商店的total,因此您的方法非常接近,但您需要更新它以增加每个键的总数,而不是在每次迭代时替换它。

以下是如何完成此操作的示例:

item1 = {name: "White Bread", price: 1.20, shop: "Baker" }
item2 = {name: "Whole Milk", price: 0.80, shop: "Corner Shop"}
item3 = {name: "Gorgonzola", price: 10.20, shop: "Cheese Shop"}
item4 = {name: "Mature Cheddar", price: 5.20, shop: "Cheese Shop"}
item5 = {name: "Limburger", price: 6.35, shop: "Cheese Shop"}
item6 = {name: "Newspaper", price: 1.205, shop: "Corner Shop"}
item7 = {name: "Ilchester", price: 3.99, shop: "Cheese Shop"}
list = [item1, item2, item3, item4, item5, item6, item7]

totals = {}
list.each do |item|
  key = item[:shop].to_sym
  if totals[key] == nil
    # initialize the total for this shop
    totals[key] = item[:price]
  else
    # increase the previous total for this shop
    totals[key] = totals[key] + item[:price]
  end
end

puts totals
© www.soinside.com 2019 - 2024. All rights reserved.