【问题标题】:cheapest combination of items in python dataframepython数据框中最便宜的项目组合
【发布时间】:2014-03-21 08:35:43
【问题描述】:

我在 python 中有这个 csv 文件

SHOP_ID, COST, ITEM
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

我已经在 python 中将此文件作为数据框读取。

现在假设我输入 A、B、C、D 作为输入,并想从我的数据框中为这个用户输入找到最便宜的项目组合,那么我应该得到:-

SHOP_ID=1
A,B(1.00)+A,C(1.50)+D(1.00) = 3.50

用户将获得 A,A,B,C,D 即额外的 A,但只要总成本最低,我们不关心用户是否获得额外的物品作为免费赠品。

我不知道如何解决这个问题。任何帮助将不胜感激。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这是一种方法:

    def build_shops(shop_text):
        shops = {}
        for item_info in shop_text:
            shop_id,cost,items = item_info.replace(' ', '').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, []]
        for item in items:
            if item not in shop:
                return [float('inf'), []]
        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)
        result_all_shops = []
        for shop_id,shop_info in shops.iteritems():
            (price, solution) = solve_one_shop(shop_info, required_items)
            if price != float('inf'):
                result_all_shops.append([shop_id, price, solution])
        if len(result_all_shops) == 0:
            print('No shop has all required items')
            return
        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)
    

    测试:

    input_data = [
        '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',
    ]
    required_items = ['A','B','C','D']
    solver(input_data, required_items)
    

    输出:

    SHOP_ID=1
    D(1.00)+A,C(1.50)+A,B(1.00) = 3.50
    

    请注意我使用的是:

    1, 1.00, A+B
    

    而不是

    1, 1.00, "A, B"
    

    作为输入格式,只是为了更容易格式化。您可以根据您的格式修改函数“build_shops”。

    这个解决方案基本上是:选择项目'A',然后计算集合的解决方案('B','C','D')。为了计算解决方案('B','C','D'),它选择'B'并计算集合('C','D')。这是一种分而治之(http://en.wikipedia.org/wiki/Divide_and_conquer_algorithms)。关键代码是:

        sub_set = [x for x in items if x not in combo]
        price_sub_set,solution = solve_one_shop(shop, sub_set)
    

    为了帮助理解代码,我将“build_shops”的输出粘贴到这里:

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

    此解决方案迭代所有可能的组合,这是蛮力。如果数据集非常大,那么效率不会很高。

    测试用例 2:

    input_data = [
        '1, 2.00, burger',
        '1, 1.25, tofu',
        '1, 2.00, tuna',
        '1, 1.00, salad',
        '1, 1.00, burger+tofu',
        '1, 1.50, burger+tuna',
        '1, 2.50, burger+salad',
        '2, 3.00, burger',
        '2, 1.00, tofu',
        '2, 1.20, tuna',
        '2, 1.25, salad',
    ]
    required_items = ['burger','tofu','tuna','salad']
    solver(input_data, required_items)
    

    输出 2:

    SHOP_ID=1
    salad(1.00)+burger,tuna(1.50)+burger,tofu(1.00) = 3.50
    

    【讨论】:

    • 谢谢zee,能否请您简要介绍一下代码逻辑。
    • @sunita,我在答案中插入了一点解释。您可以在“这个解决方案基本上可以......”查看它
    • 您好,您的代码无法正常工作。我得到这个: SHOP_ID=1 D(1.00)+A,C(1.50)+A,B(1.00) = 1.00
    • 在 spyder 中运行代码 LINE_NO:46 " sln_str = [','.join(items)+'(%0.2f)'%price for (price,items) in solution]" 列表理解从第 44 行重新定义价格。LINE_NO:44 "shop_id,price,solution = min(result_all_shops, key=(lambda x: x[1]))"
    • @sunita,很抱歉有一个错误,正如您所看到的——重新定义了变量。我已经对答案进行了一些编辑以修复它(将“价格”更改为“总价格”)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    相关资源
    最近更新 更多