搜索具有可变列数的CSV

时间:2013-11-15 21:59:42

标签: ruby csv file-io

我可以用一些帮助来思考我正在解决的难题。我打算在Ruby中处理它,但可能使用另一种语言,如Javascript / Node。我需要帮助解决问题和设计。

我正在开发一个命令行程序,它读取CSV中的内容,根据参数搜索CSV,然后根据它找到的内容生成输出。

CSV行具有两种格式之一。一个很简单的是餐馆,食品和价格清单:

restaurant ID, price, item label

但对于提供组合餐的餐厅,可以有任意数量的餐馆 价值餐中的物品:

restaurant ID, price, item 1 label, item 2 label, ...

所以我的想法是你可以运行这个程序,使用CSV文件的参数来阅读你要吃的食物,然后输出他们应该去的餐馆,以及它们花费的总价。只要总成本最小化,就可以购买额外的物品。

示例data.csv

1, 4.00, burger 
1, 8.00, tofu_log 
2, 5.00, burger 
2, 6.50, tofu_log

$ foodfinder.rb data.csv burger tofu_log 
=> 2, 11.5

与包含多个食品的行类似:

5, 4.00, extreme_fajita
5, 8.00, fancy_european_water
6, 5.00, fancy_european_water
6, 6.00, extreme_fajita, jalapeno_poppers, extra_salsa

$ foodfinder.rb data.csv fancy_european_water extreme_fajita
=> 6, 11.0

由于数据规范化不是一个选项 - 我无法将它们推入数据库 - 我想知道如何考虑如何以有效的方式解析CSV。还有一些行有多个食品我不知道如何存储这些。我猜我想要将行导入哈希,然后以某种方式搜索哈希。任何指导,巫师?

2 个答案:

答案 0 :(得分:0)

使用Ruby,我会跳过标准的CSV库,只需加载行,将它们分成最多三个部分,然后将第三个转换为数组。从那时起,您就拥有了所有需要:

records = file.map { |row|
  row.split(/,\s?/, 3)
}.map { |arr|
  [arr[0].to_i, arr[1].to_f, arr[2].split(/,\s?/)]
}

现在您的记录将是:

[
  [5, 4.00, ["extreme_fajita"]],
  [5, 8.00, ["fancy_european_water"]],
  [6, 5.00, ["fancy_european_water"]],
  [6, 6.00, ["extreme_fajita", "jalapeno_poppers", "extra_salsa"]]
]

您可以利用您的知识解决此数据中已完成问题的NP完全问题。

答案 1 :(得分:0)

这些数据很容易用标准CSV library和一点阵列争论来解析:

data = CSV.open('data.csv')
          .map { |r| [ r[0], r[1], r[2..-1].map(&:strip) ] }

这会在data

中为您提供此功能
data = [
    ['5', '4.00', ['extreme_fajita']],
    ['5', '8.00', ['fancy_european_water']],
    #...
]

从那里可以轻松构建您需要的任何索引结构。

但是,如果您只想查找'extra_salsa'行,请使用select代替map

want = CSV.open('x.csv')
          .select { |r| r[2..-1].map(&:strip).include?('extra_salsa') }

并清理want以进行打印,但需要这样做。

每次脚本运行时你都会在整个CSV中旋转,所以你应该在扫描时搜索它,如果你只进行一次搜索,建立中间索引数据结构只是浪费时间每次运行。