在列表列表中查找最大重叠

时间:2017-03-06 13:54:24

标签: python algorithm list overlap

我有两个列表列表:

a = [[0, 1, 5], [2], [3], [4], [6, 7], [8, 9, 10, 11], [12], [13], [14], [15]]
b = [[0, 1], [2, 3], [4], [5], [6, 7], [8, 9, 10, 11], [12], [13, 14], [15]]

如何找到列表值之间的最大重叠,并构建具有此最大重叠的新列表列表。 换句话说,我正在寻找一个函数f,它通过合并重叠列表来最大化列表大小。

此示例的函数f的所需结果将是:

f(a,b) = [[0, 1, 5], [2, 3], [4], [6, 7], [8, 9, 10, 11], [12], [13, 14], [15]] 

2 个答案:

答案 0 :(得分:7)

您可以使用disjoint-set structure的变体来解决此问题:对于每个列表[a,b,c],您统一 a b和{ {1}} a。您对两个列表执行此操作,然后派生结果根。

Here我们可以修改一个简单的 disjunct-set 算法:

c

(为与原始联合集算法的语义差异添加了粗体字。)

这会产生:

from collections import defaultdict

def parent(u,mapping):
    if mapping[u] == u:
        return u
    mapping[u] = parent(mapping[u],mapping)
    return mapping[u]

def relation(array,mapping=None):
    if mapping is None:
        mapping = {}

    for e in array:
        if len(e) > 0:
            u = e[0]
            if u not in mapping:
                mapping[u] = u
            for v in e[1:]:
                if v not in mapping:
                    mapping[v] = v
                mapping[parent(u,mapping)] = parent(v,mapping)
    return mapping

def f(a,b):
    mapping = {}
    relation(a,mapping)
    relation(b,mapping)

    results = defaultdict(set)
    for u in mapping.keys():
        results[parent(u,mapping)].add(u)
    return [list(x) for x in results.values()]

结果没有排序,因为我们使用了一个集合。不过,如果你愿意,你可以通过改变>>> f(a,b) [[2, 3], [4], [0, 1, 5], [6, 7], [8, 9, 10, 11], [12], [13, 14], [15]] 来轻松地在每个元组的第一个元素上对它进行排序:

f

产生:

def f(a,b):
    mapping = {}
    relation(a,mapping)
    relation(b,mapping)

    results = defaultdict(set)
    for u in mapping.keys():
        results[parent(u,mapping)].add(u)
    return sorted([list(x) for x in results.values()],key=lambda t:t[0])

此解决方案的优点在于,如果>>> f(a,b) [[0, 1, 5], [2, 3], [4], [6, 7], [8, 9, 10, 11], [12], [13, 14], [15]] a本身中存在重叠,它也可以正常工作,您可以轻松地将解决方案概括为使用任意数量的列表(例如bab)。

答案 1 :(得分:0)

当我理解正确时,以下将会这样做:

[l for l in a if not any(all(x in l2 for x in l) for l2 in b)] + 
[l for l in b if not any(all(x in l2 for x in l) for l2 in a)] + 
[l for l in a if l in b]

第一个词会产生a中的所有列表,这些列表不属于b中列表的一部分;第二个术语会产生b中的所有列表,这些列表是a中列表的注释部分;第三个术语产生所有列表,这些列表都在ab中。

对于您的示例,这会产生以下结果:

[[0, 1, 5], [2, 3], [13, 14], [4], [6, 7], [8, 9, 10, 11], [12], [15]]