【问题标题】:Create product bundle by matching user input to product features recursively通过将用户输入与产品功能递归匹配来创建产品包
【发布时间】:2021-05-23 11:48:14
【问题描述】:

我正在从事产品包创建和推荐项目。捆绑和推荐必须根据用户输入实时进行。

条件是 1.产品包应尽可能覆盖用户输入。 2. 推荐项目中用户输入的重复应该更少。

user_input=['a','b','c']

d1=['a','c','d']
d2=['a','b','e','f']
d3=['a','c','b','f']
d4=['b']
d5=['g','e','a']
d6=['g']

expected output - d1 + d4, d3, d1+d2,d5+d4+d1

以下是我的代码,它给出了结果,但显示了重复的结果,也没有显示所有组合。任何帮助表示赞赏。

dlist=[d1,d2,d3,d4,d5,d6]
diff_match=[]
# find match n diff of each product based on user input
for i in range(len(dlist)):
    match=set(user_input).intersection(set(dlist[i]))
    #print("match is",match)
    diff=set(user_input).difference(set(dlist[i]))
    #print("diff is",diff)
    temp={'match':match,'diff':diff}
    diff_match.append(temp)
    
for i in range(len(diff_match)):
    # if match is found, recommend the product alone
    diff_match_temp=diff_match[i]['match']
    print("diff match temp is",diff_match_temp)
    if diff_match_temp==user_input:
        print ("absolute match")
    #scenario where the user input is subset of product features, seperate from partial match
    elif (all(x in list(diff_match_temp) for x in list(user_input))):
        print("User input subset of product features")
        print("The parent list is",diff_match[i]['match'])
        print("the product is", dlist[i])
    else:
        '''else check if the difference between user input and the current product is fulfilled by other product, 
        if yes, these products are bundled together'''
        for j in range(len(diff_match)):
            temp_diff=diff_match[i]['diff']
            print("temp_diff is",temp_diff)
            # empty set should be explicitly checked to avoid wrong match
            if (temp_diff.intersection(diff_match[j]['match'])==temp_diff and len(temp_diff)!=0 and list(temp_diff) != user_input) :
            #if temp_diff==diff_match[j]['match'] and len(temp_diff)!=0 and list(temp_diff) != user_input :
                print("match found with another product")
                print("parent is",dlist[i])
                print("the combination is",dlist[j] )

【问题讨论】:

    标签: python python-3.x list recursion recommendation-engine


    【解决方案1】:

    要递归地执行此操作,您可以创建一个函数,该函数返回具有最大组件覆盖率的产品并递归以完成包含剩余组件的捆绑包:

    def getBundles(C,P):
        cSet     = set(C) # use set operations,  largest to smallest coverage
        coverage = sorted(P.items(),key=lambda pc:-len(cSet.intersection(pc[1])))
        for i,(p,cs) in enumerate(coverage):
            if cSet.isdisjoint(cs):continue          # no coverage
            if cSet.issubset(cs): yield [p];continue # complete (stop recursion)
            remaining = cSet.difference(cs)   # remaining components to bundle
            unused    = dict(coverage[i+1:])  # products not already bundled
            yield from ([p]+rest for rest in getBundles(remaining,unused))
    

    输出:

    prods = {"d1":['a','c','d'],
             "d2":['a','b','e','f'],
             "d3":['a','c','b','f'],
             "d4":['b'],
             "d5":['g','e','a'],
             "d6":['g']}
    
    user_input=['a','b','c']
    
    for bundle in getBundles(user_input,prods):
        print(bundle)
    
    ['d3']
    ['d1', 'd2']
    ['d1', 'd4']
    

    请注意,诸如 ['d5','d1','d2'] 之类的冗余组合被排除在外,因为 d1+d2 涵盖了 d5 涵盖的所有内容以及更多内容,因此 d5 是多余的。相同产品的排列也被排除在外(例如 d1+d2 与 d2+d1 相同)

    [编辑]

    如果您需要提供冗余组合(可能作为扩展选择选项),您可以编写一个稍微不同的递归函数,不会排除它们。在呈现结果时,您还应该按照最接近的顺序对结果进行排序:

    def getBundles(C,P,remain=None,bundle=None):
        cSet  = set(C)                               # use set operations
        if remain is None: remain,bundle = cSet,[]   # track coverage & budle
        prods = list(P.items())                      # remaining products
        for i,(p,cs) in enumerate(prods):
            if cSet.isdisjoint(cs):continue         # no coverage
            newBundle = bundle+[p]                  # add product to bundle
            if remain.issubset(cs): yield newBundle # full coverage bundle 
            toCover = remain.difference(cs)         # not yet covered 
            unused  = dict(prods[i+1:])             # remainin products
            yield from getBundles(C,unused,toCover,newBundle) # recurse for rest
    

    输出:

    prods = {"d1":['a','c','d'],
             "d2":['a','b','e','f'],
             "d3":['a','c','b','f'],
             "d4":['b'],
             "d5":['g','e','a'],
             "d6":['g']}    
    user_input=['a','b','c']
    
    for bundle in sorted(getBundles(user_input,prods),
                         key=lambda b:sum(map(len,(prods[p] for p in b)))):
        print(bundle)
    
    ['d1', 'd4']
    ['d3']
    ['d3', 'd4']
    ['d1', 'd2']
    ['d1', 'd3']
    ['d1', 'd4', 'd5']
    ['d3', 'd5']
    ['d1', 'd2', 'd4']
    ['d1', 'd3', 'd4']
    ['d2', 'd3']
    ['d3', 'd4', 'd5']
    ['d2', 'd3', 'd4']
    ['d1', 'd2', 'd5']
    ['d1', 'd3', 'd5']
    ['d1', 'd2', 'd3']
    ['d1', 'd2', 'd4', 'd5']
    ['d1', 'd3', 'd4', 'd5']
    ['d2', 'd3', 'd5']
    ['d1', 'd2', 'd3', 'd4']
    ['d2', 'd3', 'd4', 'd5']
    ['d1', 'd2', 'd3', 'd5']
    ['d1', 'd2', 'd3', 'd4', 'd5']
    

    【讨论】:

    • 非常感谢您的回答。如果我也想拥有 ['d5','d1','d2'] 怎么办?如果说在这种情况下成本或位置更适合客户需求,我可能也必须显示此选项。
    • 我似乎无法进行简单的更改来包含这些冗余组合,同时仍排除排列。可能需要一组不同的条件/递归。
    • 这显示了太多的冗余。我想知道我们是否可以拥有像最佳匹配和冗余匹配这样的标志。
    • 您可以使用两个函数(一个用于最佳匹配,一个用于冗余组合)但是,为了不得到太多冗余组合,需要一个附加条件,例如限制多少重复组件 一个完全冗余的产品是允许有的。 (我建议为此发布一个新问题)。
    猜你喜欢
    • 1970-01-01
    • 2020-10-15
    • 2011-03-09
    • 2021-09-06
    • 2011-12-27
    • 1970-01-01
    • 2013-04-20
    • 2011-12-06
    • 1970-01-01
    相关资源
    最近更新 更多