【问题标题】:How can you remove superset lists from a list of lists in Python?如何从 Python 中的列表列表中删除超集列表?
【发布时间】:2018-06-01 01:25:19
【问题描述】:

我在 Python 中有一个列表,如下所示:

[[1,2,3],[2,3],[2,4,3],[4,5],[5]]

我想删除作为另一个内部列表的超集的所有内部列表(一个包含另一个列表的所有元素的列表,但还有其他元素)。对于上面的示例,删除超集应导致以下结果:

[[2,3],[5]]

我怎样才能做到这一点?

【问题讨论】:

    标签: python python-3.x list nested-lists


    【解决方案1】:

    如果一个集合更小,它只能是另一个集合的子集,因此通过按大小升序迭代集合,我们可以根据先前找到的最小子集检查每个元素,以了解它是否是最小子集。

    def get_minimal_subsets(sets):
        sets = sorted(map(set, sets), key=len)
        minimal_subsets = []
        for s in sets:
            if not any(minimal_subset.issubset(s) for minimal_subset in minimal_subsets):
                minimal_subsets.append(s)
    
        return minimal_subsets
    
    l = [[1,2,3],[2,3],[2,4,3],[4,5],[5]]
    
    print(get_minimal_subsets(l))  # [{5}, {2, 3}]
    

    【讨论】:

    • 你的代码很干净。如果您查看我的答案,您可以通过每次迭代删除匹配的超集来删除每次迭代的 minimum_subsets 循环。我的假设是这比切片每个循环的成本更高,但我还没有确定它的时间。
    【解决方案2】:

    您可以使用列表推导:

    d = [[1,2,3],[2,3],[2,4,3],[4,5],[5]]
    new_d = [i for i in d if not any(all(c in i for c in b) and len(b) < len(i) for b in d)]
    

    输出:

    [[2, 3], [5]]
    

    【讨论】:

      【解决方案3】:

      这里是:

      super=[[1,2,3],[2,3],[2,4,3],[4,5],[5]]
      subset=[s for s in super if not any(set(s).issuperset(set(i)) and len(s)>len(i) for i in super)]
      

      输出:

      >>> subset
      [[2, 3], [5]]
      

      【讨论】:

        【解决方案4】:

        我最终得出了与@Olivier Melançon 相同的想法。您可以使用升序丢弃子集并在 O(n^2) * O(子集计算) 中运行。

        input = [[1,2,3],[2,3],[2,4,3],[4,5],[5]]
        sets = [set(x) for x in input]
        sets.sort(key=len)
        
        subsets = []
        while sets != []:
            cur = sets[0]
            subsets.append(cur)
            sets = [x for x in sets[1:] if not cur <= x]
        
        output = [list(x) for x in subsets]
        print(output)
        

        【讨论】:

        • 您应该以相反的顺序排序并弹出最后一个 O(1) 的元素,而不是切片。首先:sets.sort(key=len, reverse=True) 然后cur = sets.pop(); subsets.append(cur)。这允许从列表理解中删除切片:sets = [x for x in sets if not cur &lt;= x].
        • 你将如何做到这一点:保留超集,但丢弃子集?我使用 lambda 函数执行此操作,但随着主列表变大,我的性能受到了巨大影响:clean_list = filter(lambda f: not any(set(f) &lt; set(g) for g in main_list), main_list)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-23
        • 1970-01-01
        • 2017-09-12
        • 2017-11-02
        • 2017-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多