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

Python从嵌套列表中最小数量的重复值创建列表,python,Python,我有一个口述 whs = { 'ID1' : ['code1', 'code2', 'code3'], 'ID2' : ['code2', 'code5', 'code3'], 'ID3' : ['code6', 'code7', 'code8'], 'ID4' : ['code3', 'code5', 'code6'], } 我需要做的是建立一个新的列表 submit = [ { 'codes' : ['code3', ],

我有一个口述

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', ]
}
奇怪的是,是否有一种我没有想到的更简单的方法,我想我可以设置更多的嵌套循环来逐件比较所有的东西,尽管这看起来很不和谐


提前谢谢你

所以在我看来你有一个问题,它是NP完全的。不仅如此,您似乎还需要最小尺寸的所有可能的封套。您的ID列表创建了宇宙集,而您的每个代码都创建了宇宙的一个子集

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

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


如果您需要得到绝对正确的答案,您可能需要尝试整数规划方法(如线性规划)。有用于此算法的软件包和库

我通过构建一个包含所有潜在添加项的树,然后在这些添加项中找到最便宜的选项来解决这个问题。以下是一个有效的(尽管丑陋且未优化)示例:


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

正如其他人所说,这是一个优化问题,对于大型数据集来说并不简单。但作为第一步,将每个产品的仓库列表转换为每个仓库的产品列表至少很容易

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)可以在两个订单中获得产品。选择“最佳”将需要额外的信息,如定价,以进行优化。

您的输出结构似乎有些奇怪。您在输出中到底想要什么?什么规则定义了它的结构?最终目标是从不同的仓库(代码)获取可用的产品(ID)列表从最少数量的仓库创建一个订单列表——这一部分在解析为XML提交查询之前进行排序——这种结构似乎是在函数之间传递数据的最简单方式——尽管我很乐意接受建议在您的示例中,您并没有在输出中包含所有代码。是否有其他必须包含的代码列表?还是您总结了输出?仅供参考,您的问题似乎是set cover的一个实例,这将是“困难的”,因此希望您没有大型数据集。您正在寻找的函数会在数据上建立索引。这对数据库来说非常重要。如果数据大小非常小,则需要添加修剪,以便在找到较短的答案后不会枚举树的分支。如前所述,对于非常大的数据集,可能不是最佳解决方案。幸运的是,该应用程序将在任何时候使用的设置都应该保持相当小。非常感谢您发布工作代码-我发现自己从您的方法中学到了一些东西。@ZackBloom我更关心的是在
构建树期间的修剪问题。
@goldsz啊,公平点。您可以通过集成树构建和路径查找来提高它的性能。重新访问此函数时,我发现它并不是我想要的-此版本返回一个dict,ID为键,代码列表为var-诀窍是每次添加都会覆盖现有ID,因此它只返回最后一个ID。要运行结果当len(“codes”)>0时,通过另一个过程确定最近的仓库