Python从嵌套列表中的最小数量的重复值创建列表

时间:2011-10-14 23:49:33

标签: python

我有一个Dict

whs = {
    'ID1' : ['code1', 'code2', 'code3'],
    'ID2' : ['code2', 'code5', 'code3'],
    'ID3' : ['code6', 'code7', 'code8'],
    'ID4' : ['code3', 'code5', 'code6'],
}

我需要做的是构建一个看起来像

的新列表
submit = [
    {
        'codes' : ['code3', ],
        'ids' : ['ID1', 'ID2', 'ID4'],
    },
    {
        'codes' : ['code6', 'code7', 'code8'],
        'ids' : ['ID3', ],
    }
]

到目前为止我有什么

def ParseAvailable(self, whs):
    separate = whs.keys()
    submit = []
    while len(separate) > 0:
        avail = {
            'codes' : [],
            'ids' : [],
        }
        for num, item in enumerate(separate):
            if len(avail['codes']) == 0:
                avail['codes'] = whs[item]
                avail['ids'].append(item)
            else:
                avail_all = list(set(avail['codes']) & set(whs[item]))
                print '%s : %s' % (item, avail_all)
                if len(avail_all) > 0:
                    avail['codes'] = avail_all
                    avail['ids'].append(item)
            if len(avail['codes']) > 0:
                del separate[num]
        submit.append(avail)
    return submit

返回:

[
    {
        'ids': ['ID4', 'ID3'], 
        'codes': ['code6']
    },
    {
        'ids': ['ID2'], 
        'codes': ['code2', 'code5', 'code3']
    },
    {
        'ids': ['ID1'],
         'codes': ['code1', 'code2', 'code3']
    }
]

除了ID1& ID2应合并为

{
    'ids' : ['ID1', 'ID2',],
    'codes' : ['code2', 'code3', ]
}

好奇如果有一种我没有想过的更容易的方法,我可以设置一些更多的嵌套循环来逐一比较所有东西,虽然看起来相当单调

提前感谢

3 个答案:

答案 0 :(得分:2)

我通过构建所有潜在添加的树来攻击它,然后找到其中最便宜的选项。这是一个有效的(尽管是丑陋的,未经优化的)例子:

https://gist.github.com/1288835

树将以p * w节点结束,其中p是产品数量,w(p)是每个产品的平均仓库数量。

答案 1 :(得分:0)

所以我觉得你有一个set cover问题,这是NP完全的。不仅如此,但似乎您想要所有可能的最小尺寸的套装。您的ID列表会创建Universe集,并且您的每个代码都会创建Universe的子集。

对于简单的迭代循环,除了尝试所有可能的代码组合之外,您实际上没有其他选择。如果您有大型数据集,则无法运行。

维基百科文章提到了一种有效的算法(贪婪算法),不能保证找到最佳解决方案,但解决方案中的错误是有限的。该算法迭代地添加包含宇宙中最多未覆盖元素的子集。

如果您需要获得绝对正确的答案,您可能需要尝试整数编程方法(如线性编程)。该算法有软件包和库。

答案 2 :(得分:0)

正如其他人所说,这是一个优化问题,对于大型数据集来说并非易事。但作为第一步,至少可以轻松地将每个产品的仓库列表转换为每个仓库的产品列表。

whs = {
    'ID1' : ['code1', 'code2', 'code3'],
    'ID2' : ['code2', 'code5', 'code3'],
    'ID3' : ['code6', 'code7', 'code8'],
    'ID4' : ['code3', 'code5', 'code6'],
}

a = []
b = []
for k,v in whs.items():
    for j in v:
        a.append((j,k))
        b.append((j,[]))
inv = dict(b)
for j in a:
    inv[j[0]].append(j[1])

print("Inventory:")
for k,v in inv.items():
    print(k,v)

运行时,会打印:

Inventory:
code1 ['ID1']
code2 ['ID2', 'ID1']
code3 ['ID4', 'ID2', 'ID1']
code5 ['ID4', 'ID2']
code6 ['ID4', 'ID3']
code7 ['ID3']
code8 ['ID3']

从简单的例子中可以看出,没有任何解决方案可以将所有产品整合到一个订单中,而且有几种解决方案(code2 + code6,code3 + code6,code3 + code7,code3 + code8)可以获得它们两个命令。选择“最佳”将需要额外的信息,例如定价,以进行优化。