python数据框架中最便宜的项目组合

python数据框架中最便宜的项目组合,python,pandas,Python,Pandas,我有一个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作为输入,并希望从我的数据框中为该用户输入找到最便宜的项目组合,那么我应该得到:

我有一个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,但只要总成本最低,我们不关心用户是否获得额外的免费物品

我不知道如何着手解决这个问题。非常感谢您的帮助。

以下是一种方法:

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)
测试:

输出:

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')。这是一种分而治之的方法()。关键代码是:

    sub_set = [x for x in items if x not in combo]
    price_sub_set,solution = solve_one_shop(shop, sub_set)
为了帮助理解代码,我将“build_shops”的输出粘贴到这里:

这个解决方案迭代所有可能的组合,这是蛮力。因此,如果数据集非常大,将不会非常有效

测试用例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,我在答案中插入了一点解释。你可以在“这个解决方案基本上是这样做的……”中查看它。嗨,zee,你的代码不起作用。我明白了:SHOP_ID=1d(1.00)+A,C(1.50)+A,B(1.00)=1.00在spyder行中运行您的代码_NO:46“sln_str=[','。join(items)+'(%0.2f)'(price,items)in solution]“列表理解从第44行重新定义了价格。第44行“shop\u id,price,solution=min(result\u all\u shop,key=(lambda x:x[1])”@sunita,很抱歉出现了一个bug,正如您所看到的——变量被重新定义。我对答案做了一些修改(将“价格”改为“总价”)
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)
SHOP_ID=1
salad(1.00)+burger,tuna(1.50)+burger,tofu(1.00) = 3.50