【问题标题】:python code works on one file but fails on otherpython代码在一个文件上工作,但在另一个文件上失败
【发布时间】:2014-05-03 23:24:27
【问题描述】:

大家好,我有这个代码,它打印出商品的最低成本和餐厅 ID。客户不想访问多家餐厅。因此,例如,如果他要求“A,B”,那么代码应该打印同时提供它们的商店,而不是将用户需求分散到不同的餐厅(即使某些餐厅提供的价格便宜)。

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

一切都很好,但是代码在两个格式相同的输入文件(在 input.csv 上失败但在 input-2.csv 上运行)上的行为奇怪地不同,它为一个文件提供正确的输出,而对另一个文件则失败。这是我需要您帮助修复的唯一微小错误。请帮帮我,我想我已经撞墙了,无法超越这一切。

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]
    if first_item in shop:
        print "SHOP",shop.get(first_item)
    for (price,combo) in shop[first_item]:
        #print "items,combo=",items,combo
        sub_set = [x for x in items if x not in combo]
        #print "sub_set=",sub_set
        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-1.csv','rb')    
solver(shop_text,['burger'])

=====input-1.csv=====restaurant_id、价格、商品

1,2.00,burger
1,1.25,tofulog
1,2.00,tofulog
1,1.00,chef_salad
1,1.00,A+B
1,1.50,A+CCC
1,2.50,A
2,3.00,A
2,1.00,B
2,1.20,CCC
2,1.25,D

=====输出和错误====:

{'1': {'A': [[1.0, ['A', 'B']], [1.5, ['A', 'CCC']], [2.5, ['A', 'D']]], 'B': [[1.0, ['A', 'B']]], 'D': [[2.5, ['A', 'D']]], 'chef_salad': [[1.0, ['chef_salad']]], 'burger': [[2.0, ['burger']]], 'tofulog': [[1.25, ['tofulog']], [2.0, ['tofulog']]], 'CCC': [[1.5, ['A', 'CCC']]]}, '2': {'A': [[3.0, ['A']]], 'B': [[1.0, ['B']]], 'D': [[1.25, ['D']]], 'CCC': [[1.2, ['CCC']]]}}
SHOP [[2.0, ['burger']]]
Traceback (most recent call last):
  File "work.py", line 55, in <module>
    solver(shop_text,['burger'])
  File "work.py", line 43, in solver
    (price, solution) = solve_one_shop(shop_info, required_items)
  File "work.py", line 26, in solve_one_shop
    for (price,combo) in shop[first_item]:
KeyError: 'burger'

而如果我在 input-2.csv 上运行相同的代码,并查询求解器(shop_text,['A','CCC']),我会得到正确的结果

=====input-2.csv======

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

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

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

【问题讨论】:

    标签: python csv dictionary


    【解决方案1】:

    如果你这样做,你可以找出错误:

    在您的solve_one_shop 方法中,在first_item = items[0] 行之后打印字典shop。这样做会打印出来:

    {'A': [[3.0, ['A']]], 'B': [[1.0, ['B']]], 'D': [[1.25, ['D']]], 'CCC': [[1.2, ['CCC']]]}

    所以,burger 不是它的键之一,因此它会抛出一个 KeyError

    添加这一行: 2,1.25,burger 到您的 input.csv 文件的末尾,您的代码可以正常工作。

    在 try except 块中读取 shop 字典中的值,以处理可能不存在项目的情况。

    注意:
    在您的方法build_shops 中:

    shop_id,cost,items = item_info.replace('\n', '').split(',')
    

    虽然去掉了换行符,但并没有去掉回车符。要解决此问题,请执行以下操作:

    shop_id,cost,items = item_info.replace('\n', '').replace('\r', '').split(',')
    

    希望这会有所帮助。

    【讨论】:

    • 嗨 Warun,谢谢,但我认为你弄错了。我给出了两个测试文件的输出。请参阅第一个 input-1.csv 文件确实有汉堡的条目,但我仍然收到未找到汉堡的 KeyError。而在 input-2.csv 上,代码运行得非常好。如您所见,这两个文件具有相同的结构(逗号分隔)和格式,但是为什么其中一个提供输出而另一个不提供输出?
    • @sunita 使用 input-2.csv 代码运行良好,因为 CCC 存在于 shop_id 值 1 和 2 中,因此不会在 for (price,combo) in shop[first_item]: 出现错误987654336@ 虽然有burgershop_id 值1,但它没有burger 对应shop_id 2,因此在for (price,combo) in shop[first_item]: 处给出错误
    • 谢谢warun,但是我该如何克服这个错误呢?如果可能的话,请您修复我的代码。非常感谢
    • 感谢您指出warun。不过有一个小问题。如果我调用 ---- shop_text = open('input-1.csv','rb') solver(shop_text,['burger', 'D']) 上的代码。我收到 TypeError,因为这两家商店中的任何一家都不提供“汉堡”和“D”商品。而不是抛出 TypeError,我希望程序只输出 - “项目不可用”
    【解决方案2】:

    我想我已经解决了...

    solve_one_shop

    for 循环应该只发生在if 内,否则你会得到一个KeyError。此外,我已对其进行了更改,使其仅在 all_possible 包含任何内容时返回(空的 list 评估为 False

    编辑为了防止 TypeError 我已经分配了一个临时值 this_subset 并且循环的其余部分只发生它不是 None

    def solve_one_shop(shop, items):
        if len(items) == 0:
            return [0.0, []]
        all_possible = []
        first_item = items[0]
        if first_item in shop:
            for (price,combo) in shop[first_item]:
                sub_set = [x for x in items if x not in combo]
                this_subset = solve_one_shop(shop, sub_set)
                if this_subset is not None:
                    price_sub_set,solution = this_subset
                    solution.append([price,combo])
                    all_possible.append([price+price_sub_set, solution])
    
        if all_possible:
            cheapest = min(all_possible, key=(lambda x: x[0]))
            return cheapest
    

    求解器

    我已将solve_one_shop 的返回值分配给一个中间变量。如果是None,则该店铺未添加到result_all_shops

    编辑如果result_all_shops为空,则打印一条消息而不是尝试查找min

    def solver(input_data, required_items):
        shops = build_shops(input_data)
        result_all_shops = []
        for shop_id,shop_info in shops.iteritems():
            this_shop = solve_one_shop(shop_info, required_items)
            if this_shop is not None:
                (price, solution) = this_shop
                result_all_shops.append([shop_id, price, solution])
    
        if result_all_shops:
            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)
        else:
            print "Item not available"
    

    【讨论】:

    • 谢谢汤姆。它的工作,但有一个问题。如果我调用 ---- shop_text = open('input-1.csv','rb') solver(shop_text,['burger', 'D']) 上的代码。我收到一个 TypeError,因为这两个商店中的任何一个都不能同时提供“burger”和“D”项目。而不是抛出 TypeError,我希望程序只输出 - “项目不可用”
    • @sunita 这很令人困惑,你没有说你改变了你的输入数据!我在上面做了一些更改,希望可以解决这些问题。
    猜你喜欢
    • 1970-01-01
    • 2016-07-26
    • 2014-09-20
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    相关资源
    最近更新 更多