折叠列表列表以消除冗余

时间:2015-06-18 13:48:34

标签: python list

我有几个很长的相关对象列表,我想将它们分组以减少冗余。伪代码:

>>>list_of_lists = [[1,2,3],[3,4],[5,6,7],[1,8,9,10]...]
>>>remove_redundancy(list_of_lists)
[[1,2,3,4,8,9,10],[5,6,7]...]

因此,包含相同元素的列表将折叠为单个列表。折叠它们很容易,一旦我找到要合并的列表,我就可以将列表放入集合中并使用它们的联合,但我不确定如何比较列表。我是否需要执行一系列for循环?

我的第一个想法是我应该遍历并检查子列表中的每个项目是否在任何其他列表中,如果是,合并列表然后重新开始,但这似乎非常低效。我做了一些搜索并发现了这个:Python - dividing a list-of-lists to groups但我的数据没有结构化。此外,我的实际数据是一系列字符串,因此无法在任何有意义的意义上进行排序。

我可以写一些粗糙的循环代码来使这个工作,但我想知道是否有任何内置函数可以使这种比较更容易。也许是list comprehensions中的某些内容?

2 个答案:

答案 0 :(得分:2)

如果我理解你的问题,我认为这是一种合理有效的方法。这里的结果将是一组集合。

可能缺少的知识点是d & g(也写成d.intersection(g))用于查找集合交集,以及空集合是" falsey"在Python中

data = [[1,2,3],[3,4],[5,6,7],[1,8,9,10]]

result = []

for d in data:
    d = set(d)

    matched = [d]
    unmatched = []
    # first divide into matching and non-matching groups
    for g in result:
        if d & g:
            matched.append(g)
        else:
            unmatched.append(g)
    # then combine all matching groups into one group
    # while leaving unmatched groups intact
    result = unmatched + [set().union(*matched)]

print(result)
# [set([5, 6, 7]), set([1, 2, 3, 4, 8, 9, 10])]

我们从没有任何组开始(result = [])。然后我们从数据中获取第一个列表。然后,我们检查哪个现有的组与此列表相交,哪些不合适。然后我们将所有这些匹配组与列表合并(通过以matched = [d]开头实现)。我们没有触及不匹配的组(尽管其中一些最终可能会在以后的迭代中合并)。如果您在每个循环中添加一行print(result),您应该能够看到它是如何构建的。

matched中所有集合的联合由set().union(*matched)计算。供参考:

答案 1 :(得分:2)

我假设您要合并包含任何公共元素的列表。

如果任何两个列表包含至少一个公共元素(根据==运算符),这是一个有效查看(据我所知)的函数

import functools #python 2.5+
def seematch(X,Y):
    return functools.reduce(lambda x,y : x|y,functools.reduce(lambda x,y : x+y, [[k==l for k in X ] for l in Y]))

如果您使用可以在查找" true"如下所述: Stopping a Reduce() operation mid way. Functional way of doing partial running sum

我试图找到一种优雅的方法来快速迭代,但我觉得一个好的方法就是简单地循环一次并创建一个包含"合并"的其他容器。名单。您可以在原始列表中包含的列表上以及在代理列表上创建的每个新列表上循环一次。

话虽如此 - 看起来似乎还有更好的选择 - 看看你是否可以通过以前的步骤中的某种书籍来消除冗余。

我知道这是一个不完整的答案 - 希望无论如何都有帮助!