【问题标题】:KeyError when using a different csv file as input使用不同的 csv 文件作为输入时出现 KeyError
【发布时间】:2014-03-25 08:43:46
【问题描述】:

我有这段代码,它基本上用于 csv 输入文件,打印出商品/商品的最低成本和餐厅 ID。但是它在一个输入文件上抛出“KeyError”,但在另一个输入文件上却完美无瑕(两者都具有相同的风格)。有人能指出哪里错了吗?谢谢

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

  1. 我的客户不想光顾多家餐厅。因此,例如,如果他要求“extreme_fajita,jalapeno_poppers,extra_salsa”,那么代码应该打印 shop 6(它可以作为组合项目使用),而不是将用户需求分散到不同的餐厅(即使某些餐厅提供的价格便宜) )。

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


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

========输出=========

{'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

【问题讨论】:

    标签: python csv


    【解决方案1】:

    如果您的商店中没有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)))
    

    【讨论】:

    • 谢谢布尔汉。但是在 restaurant-6 有 extra_salsa。其次,如果我查询 solver(shop_text,['tuna']) ,我会得到同样的错误。第三,如果我只用字母替换项目(即“A”代表“金枪鱼”,“B”代表“豆腐”等),如果我做求解器(shop_text,['A']),我得到的正是根据需要正确的结果。为什么在两个 csv 文件上有这种不同的行为??
    • Burhan Ive 编辑了我的帖子以包含正确的输出,以及我的代码正在处理的文件。请看一下并帮我修复它。谢谢!!!!
    • Burkhan 但如果客户想要:-'extreme_fajita,jalapeno_poppers,extra_salsa' 那么您的代码将提供 2 个单独的餐厅 5,6。但客户只想在一家餐厅(如果有的话)吃他要求的饭菜,在这种情况下是餐厅 6。请看——我编辑了我的帖子并添加了“重要考虑事项”
    • 从现在开始你需要自己编辑这个:)
    猜你喜欢
    • 2020-01-31
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 2020-04-04
    • 1970-01-01
    • 2016-02-04
    相关资源
    最近更新 更多