使用不同的csv文件作为输入时的KeyError

时间:2014-03-25 08:43:47

标签: python csv

我有这个代码,基本上用于csv输入文件,打印出项目/项目的最低成本和餐馆ID。但它在一个输入文件上抛出“KeyError”,但在另一个输入文件上完美地运行(两者都是相同的样式)。有谁能指出哪里错了?感谢

一些重要注意事项:: 挑战::

  1. 我的客户不想去多家餐馆。因此,例如,如果他要求“extreme_fajita,jalapeno_poppers,extra_salsa”,那么代码应该打印商店6(它作为组合项目可用),而不是在不同的餐馆周围分散用户需求(即使一些餐馆提供它便宜)。

  2. 其次&最重要的是:假设用户要求汉堡。然后,如果某个餐厅'X'给4美元的“汉堡”,而另一家餐馆'Y'给3美元的“汉堡+金枪鱼+豆腐”,那么我们会告诉即使除了用户要求的“汉堡”之外还有额外的物品,用户也可以获得RESTAURANT'Y',但我们很乐意为它们提供额外的物品,只要价格便宜。


  3. def build_shops(shop_text):
        shops = {}
        for item_info in shop_text:
            shop_id,cost,items = item_info.replace('\n', '').split(',')
            cost = float(cost)
            items = items.split('+')
    
            if shop_id not in shops:
                shops[shop_id] = {}
            shop_dict = shops[shop_id]
    
            for item in items:
                if item not in shop_dict:
                    shop_dict[item] = []
                shop_dict[item].append([cost,items])
        return shops
    
    
    def solve_one_shop(shop, items):
        if len(items) == 0:
            return [0.0, []]
        all_possible = []
        first_item = items[0]
        for (price,combo) in shop[first_item]:
            sub_set = [x for x in items if x not in combo]
            price_sub_set,solution = solve_one_shop(shop, sub_set)
            solution.append([price,combo])
            all_possible.append([price+price_sub_set, solution])
    
        cheapest = min(all_possible, key=(lambda x: x[0]))
        return cheapest
    
    
    def solver(input_data, required_items):
        shops = build_shops(input_data)
        print shops
        result_all_shops = []
        for shop_id,shop_info in shops.iteritems():
            (price, solution) = solve_one_shop(shop_info, required_items)
            result_all_shops.append([shop_id, price, solution])
    
        shop_id,total_price,solution = min(result_all_shops, key=(lambda x: x[1]))
        print('SHOP_ID=%s' % shop_id)
        sln_str = [','.join(items)+'(%0.2f)'%price for (price,items) in solution]
        sln_str = '+'.join(sln_str)
        print(sln_str + ' = %0.2f' % total_price)
    
    
    
    shop_text = open('input.csv','rb')    
    #shops = build_shops(shop_text)
    #cheapest=solve_one_shop(shops,items)
    solver(shop_text,['A'])
    

    input.csv

    1,4.00,tuna
    1,8.00,tofu
    2,5.00,tuna
    2,6.50,tofu
    3,4.00,chef_salad
    3,8.00,steak__sandwich
    4,5.00,steak__sandwich
    4,2.50,wine_spritzer
    5,4.00,extreme_fajita
    5,8.00,fancy_eu_water
    6,5.00,fancy_eu_water
    6,6.00,extreme_fajita+jalapeno_poppers+extra_salsa
    

    但是我收到了这个错误: -

    Traceback (most recent call last):
      File "working.py", line 56, in <module>
        solver(shop_text,['extra_salsa'])
      File "working.py", line 42, in solver
        (price, solution) = solve_one_shop(shop_info, required_items)
      File "working.py", line 27, in solve_one_shop
        for (price,combo) in shop[first_item]:
    KeyError: 'extra_salsa'
    

    然而,如果我在另一个输入文件上运行它,我得到正确的答案并且不会出现任何错误。

    input.csv

    1,2.00,A
    1,1.25,B
    1,2.00,C
    1,1.00,D
    1,1.00,A+B
    1,1.50,A+C
    1,2.50,A+D
    2,3.00,A
    2,1.00,B
    2,1.20,C
    2,1.25,D
    

    ====== OUTPUT ======

    {'1': {'A': [[2.0, ['A']], [1.0, ['A', 'B']], [1.5, ['A', 'C']], [2.5, ['A', 'D']]], 'C': [[2.0, ['C']], [1.5, ['A', 'C']]], 'B': [[1.25, ['B']], [1.0, ['A', 'B']]], 'D': [[1.0, ['D']], [2.5, ['A', 'D']]]}, '2': {'A': [[3.0, ['A']]], 'C': [[1.2, ['C']]], 'B': [[1.0, ['B']]], 'D': [[1.25, ['D']]]}}
    
    SHOP_ID=1
    A,B(1.00) = 1.00
    

1 个答案:

答案 0 :(得分:2)

  

在您的商店中没有extra_salsa的地方会发生什么?

除了愤怒的莎莎爱客户外,你的脚本不起作用,因为钥匙不存在。

就像您正在检查items是否为空,您需要检查所请求的项目是否实际在店内:

def solve_one_shop(shop, items):
    if len(items) == 0:
        return [0.0, []]
    all_possible = []
    # first_item = items[0]
    for item in items:
        price,combo = shop.get(item, (0.0,[])) # This will return 
                                               # default values when
                                               # the key doesn't exist    

让我们从优化加载代码开始:

import csv

from collections import defaultdict

def build_shops(shop_file_name):
    shops = defaultdict(list)
    with open(shop_file_name, 'r') as f:
        reader = csv.reader(f, delimiter=',')
        for row in reader:
            id, cost, items = row
            cost = float(cost)
            items = items.split('+')
            shops[id].append((cost, items,))
    return shops

现在我们有一个返回字典的函数,每个键都是一个代表成本和项目列表的元组列表。

接下来,让我们优化求解器:

def solver(shops, required_items):
    result_all_shops = []
    shops_with_items = []

    for i in required_items:
        for shop, inventory in shops.iteritems():
            for price, items in inventory:
                if i in items:
                    shops_with_items.append((shop, price, i))

    if not shops_with_items:
        return []  # No shops contained the items

    for i in required_items:
        result_all_shops.append(min(filter(lambda x: x[2] == i, shops_with_items),
                                               key=lambda x: x[1]))

    return result_all_shops

最后,要加载所有内容:

if __name__ == '__main__':
    shops = build_shops('input.csv')
    items = ['extra_salsa','tofu']
    result = solver(shops, items)
    if not result:
       print('Sorry, no shops contained {}'.format(','.join(items)))
    else:
       for shop, item, price in result:
           print('Shop {} had the item {} for {}'.format(shop,price,item)))