【问题标题】:Python - Intersection of two lists of lists [duplicate]Python - 两个列表列表的交集[重复]
【发布时间】:2016-01-30 11:08:48
【问题描述】:

这是我的两个清单;

k = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,9]]
kDash = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,6], [1,2]]

我的输出应该如下;

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

我怎样才能得到这个输出?

提前谢谢你

【问题讨论】:

  • 我发现的问题是无法将列表列表转换为集合,如果可能的话,这个交叉点很容易得到
  • 请解释得到输出的逻辑。
  • 你能解释一下为什么[5, 6][5, 9] 在交叉路口吗?
  • 对不起,这是我的错误,我会改正的

标签: python list intersection


【解决方案1】:

您必须将列表转换为元组列表,然后使用交集。请注意,以下解决方案可能包含不同顺序的元素,并且显然不会出现重复项,因为我使用的是 set。

In [1]: l1 = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,9]]

In [2]: l2 = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,6], [1,2]]

In [3]: [list(x) for x in set(tuple(x) for x in l1).intersection(set(tuple(x) for x in l2))]
Out[3]: [[1, 2], [5, 6, 2], [3], [4]]

您也可以将交集保存在变量中并获取最终列表,如果顺序,则需要重复:

In [4]: intersection = set(tuple(x) for x in l1).intersection(set(tuple(x) for x in l2))

In [5]: [x for x in l1 if tuple(x) in intersection]
Out[5]: [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4]]

还有路口,以防万一你有兴趣。

In [6]: print intersection
set([(1, 2), (5, 6, 2), (3,), (4,)])

这对于大型列表非常有效,但如果列表很小,请通过@timegb 探索其他解决方案(其解决方案对于较长的列表非常不理想)

【讨论】:

    【解决方案2】:

    由于您的输出列表有重复的元素,您似乎并不真的想要一个经典的交集。一个基本的列表理解就可以了。

    >>> k = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,9]]
    >>> kDash = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,6], [1,2]]
    >>> [x for x in k if x in kDash]
    [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4]]
    

    对于大型列表,我们希望将调用 __contains__ 的时间变为 O(1) 而不是 O(n):

    >>> stuff_in_kDash = set(map(tuple, kDash))
    >>> [x for x in k if tuple(x) in stuff_in_kDash]
    [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4]]
    

    【讨论】:

    • 而如果需要去除重复元素,可以看一下this answer ;)
    • 这将比set 交叉方法慢很多。缩放类似于O(n²k),其中n 是子列表的数量,k 是每个子列表的平均长度。
    • 我刚刚意识到 OPs 输出列表有重复的元素。因此,除非规格发生变化,否则列表比较是可行的方法。
    • 我认为您的优化版本可能会重新创建 set 以在每个循环上进行测试,因此它实际上并没有解决 O(n) 问题...
    • @ShadowRanger 圣牛,你是对的,我刚刚用 set 的子类对此进行了测试,它在调用 __init__ 时会打印一些东西。我将编辑我的答案。
    【解决方案3】:

    写交集的更简洁的方法是

    {tuple(x) for x in l1} & {tuple(x) for x in l2}
    

    一个不错的选择是

    {tuple(x) for x in l1}.intersection(map(tuple, l2))
    

    【讨论】:

      【解决方案4】:

      尽管这里写的是更优雅的解决方案,但这里还有另一个

      def foo(L1,L2):
          res=[]
          for lst in L1:
              if lst in L2:
                  res.append(lst)
          return res
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-31
        • 2017-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-29
        • 2014-12-27
        相关资源
        最近更新 更多