Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 查找共同构成目标列表的最小列表的算法_Python_List_Merge - Fatal编程技术网

Python 查找共同构成目标列表的最小列表的算法

Python 查找共同构成目标列表的最小列表的算法,python,list,merge,Python,List,Merge,让我们假设我有以下几点: { 'a': [1, 2, 3], 'b': [1, 5], 'c': [3, 4, 5], 'd': [1, 3, 5], 'e': [4] } 所需的结果是['a','c'] 因为我想找到哪些数组合并在一起(并删除重复项)表单[1,2,3,4,5] 除了合并在一起形成所需结果的数组之外,我还想找到要合并以获得所需结果的最小数组(因为例如['a','d','e']也给出了所需结果,但是['a','c']是一个更好的解决方案) 注:上面的字典只是一

让我们假设我有以下几点:

{
  'a': [1, 2, 3],
  'b': [1, 5],
  'c': [3, 4, 5],
  'd': [1, 3, 5],
  'e': [4]
}
所需的结果是
['a','c']
因为我想找到哪些数组合并在一起(并删除重复项)表单
[1,2,3,4,5]

除了合并在一起形成所需结果的数组之外,我还想找到要合并以获得所需结果的最小数组(因为例如
['a','d','e']
也给出了所需结果,但是
['a','c']
是一个更好的解决方案)


注:上面的字典只是一个例子,原来的字典有很多键,每个键都有数百个值。

沿着这条线应该可以用。您需要根据您是否希望对其进行排序等进行一些调整。此解决方案假定顺序无关紧要

从最小到最大打印解决方案:

导入itertools
输入={
“a”:[1,2,3],
"b":[1,5],,
‘c’:[3,4,5],
“d”:[1,3,5],
‘e’:[4]
}
溶液=[1,2,3,4,5]
对于范围内的i(1,len(input.keys()):
对于itertools中的组合。组合(输入,i):
pot=列表(集合(itertools.chain.from_iterable(输入[k]表示组合中的k)))
如果pot==溶液:
打印(“这是一个解决方案:”,组合)

这可能不是很优雅,但它比强行通过所有组合更有效。它应该在二次时间内执行,而不是根据条目的数量和数据的传播而成指数的组合

下面的函数找到一个简短的解决方案。最可能(但不一定)是最短的

from collections import Counter

def findMerge(data,target):
    # identify candidate items (i.e. subsets of the target list)
    target     = set(target)
    candidates = {c:group for c,group in data.items() if target.issuperset(group)}
    
    # compute the overlap between candidates and check coverage
    counts = Counter( n for group in candidates.values() for n in group )
    if any(t not in counts for t in target): return [] 

    # identify candidates that are mandatory and the base set they form
    # (i.e. candidates that are the only ones with a given value)
    mandatory = { c:group for c,group in candidates.items()
                  if any(counts[n]==1 for n in group) }
    baseSet   = set().union(*mandatory.values())
    remaining = target - baseSet
    if not remaining: return list(mandatory)
   
    # identify potentially redundant candidates for remaining values
    redundant = [ (c,remaining.intersection(group))
                  for c,group in candidates.items() if c not in mandatory ]

    # remove redundant candidates (smallest first)
    # note: using combinations only on redundant keys may be affordable here
    #       and could be used to return all solutions or ensure shortest
    redundant = sorted(redundant,key=lambda cg:len(cg[1]))
    for r,rGroup in redundant:
        if all(counts[n]>1 for n in rGroup):
            counts.subtract(rGroup)
            del candidates[r]
        
    return list(candidates)
小样本的输出:

data = {
  'a': [1, 2, 3],
  'b': [1, 5],
  'c': [3, 4, 5],
  'd': [1, 3, 5],
  'e': [4]
}

print(findMerge(data,[1,2,3,4,5])) # ['a', 'c']
对于较大的样本,与组合相比,时间差异将是显著的:

data = {
  'a': [1, 2, 3],
  'b': [1, 5, 0],
  'c': [3, 2, 5],
  'd': [1, 3, 5],
  'e': [4],
  'f': [1, 2, 5],
  'g': [1, 5, 8],
  'h': [3, 4, 7],
  'i': [1, 6, 5],
  'j': [4],
  'k': [9],
  'l': [1, 3, 5],
  'm': [4],
  'n': [1, 2, 5],
  'o': [1, 5, 8],
  'p': [3, 4, 7],
  'q': [1, 5, 8],
  'r': [3, 4, 7],
  's': [1, 6, 5],
  't': [4],
  'u': [9],
}

target = [0,1,2,3,4,5,6,7,8,9]
print(findMerge(data,target)) # ['b', 'c', 'q', 'r', 's', 'u']

谢谢,我想itertools是我需要的工具。