【问题标题】:Python - Greatest Common Intersection of listsPython - 列表的最大公共交集
【发布时间】:2013-01-07 13:02:07
【问题描述】:

我想从两个给定的嵌套列表中创建一个新的嵌套列表(每个列表中都有唯一的项目),以便新的嵌套列表是两个列表的最大公共交集。

一个例子希望能帮助我弄清楚我的问题:

    old1 = [[1,2],[3,4,5],[6,7,8],[9]]
    old2 = [[1,2,3],[4,5,7],[6,8,10]]]
    new  = [[1,2],[3],[4,5],[6,8],[7],[9],[10]]

顺序并不重要,因此使用集合可能很有用。

有人有想法吗?任何帮助将不胜感激!

__

好吧,很明显,最容易得到最大公共交点的是

    new1 = filter(None,[list(set(o1) & set(o2)) for o1 in old1 for o2 in old2])
    print new1
    [[1, 2], [3], [4, 5], [7], [8, 6]]

如果您想包含仅出现在旧列表之一中的整数,您可以在之后添加它们:

    a,b = set(sum(old1, [])), set(sum(old2, []))
    c = (a | b) - (a & b)
    for d in c:
        new1.append([d])

感谢大家的帮助!

【问题讨论】:

  • 您能解释一下如何获得两个列表的“最大公共交集”吗?
  • 试试这个:[list(set(o1) & set(o2)) for o1 in old1 for o2 in old2 ]
  • 可能只是我,但我看不出新列表是如何从以前的列表中来的?你能解释一下它背后的一些逻辑吗?
  • @JonClements -- 不只是你...
  • @mgilson 谢天谢地 - 我知道我正在度过一个“金发碧眼的日子”,(为了推出一个新系统需要每天 18 小时),所以现在靠咖啡过活 - 但是 呼 :)

标签: python list nested intersection


【解决方案1】:

就个人而言,我会首先使用集合交集来计算每个交集,然后添加任何剩余的项目(即,项目仅出现在 2 个列表中的一个上):

>>> import itertools
>>> import functools
>>> 
>>> old1 = [[1,2],[3,4,5],[6,7,8],[9]]
>>> old2 = [[1,2,3],[4,5,7],[6,8,10]]
>>> 
>>> unique1 = functools.reduce(lambda a,b: set(a).union(set(b)),old1)
>>> unique2 = functools.reduce(lambda a,b: set(a).union(set(b)),old2)
>>> new = [list(set(a).intersection(set(b))) for a,b in itertools.product(old1,old2) if len(set(a).intersection(set(b))) != 0]
>>> new.extend([x] for x in unique1.symmetric_difference(unique2))
>>> 
>>> new
[[1, 2], [3], [4, 5], [7], [8, 6], [9], [10]]

a 和 b 的对称差等价于(a|b)-(a&b),它产生仅出现在 2 个集合之一中的项目。

(当然,您可以从 Grijesh Chauhan 的回答中得到一些启发,以简化交集:new = filter(None, [list(set(a) & set(b)) for a in old1 for b in old2)])

【讨论】:

  • 你已经完成了! :) .. 很好,我正在尝试,请务必阅读 Luigi 对我的回答的评论。
  • 我不确定是否可以:让old1 = [[1,2],[3,4]]old2 = [[1,2],[5,6]],我的印象是结果应该是[[1,2],[3,4],[5,6]]... 使用此代码,它将产生[[1,2],[3],[4],[5],[6]] .
  • 恕我直言,这完美!由于[3,4][5,6] 都没有出现在两个旧列表中,因此代码仅返回单个项目[3],[4],[5],[6]
【解决方案2】:

两个列表的交集:

>>> filter(None,[list(set(o1) & set(o2)) for o1 in old1 for o2 in old2 ])
[[1, 2], [3], [4, 5], [7], [8, 6]]  

什么是最大的共同点?为什么包含[9],[10]

编辑

Greatest Common Intersection 如您所述。

首先将列表转换为列表(old1ld2),二维列表到一维列表

>>> e_o1 = reduce(list.__add__, old1)
>>> e_o1
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> e_o2 = reduce(list.__add__, old2)
>>> e_o2
[1, 2, 3, 4, 5, 7, 6, 8, 10]  

使用filter()交叉路口

>>> new = filter(None,[list(set(o1) & set(o2)) for o1 in old1 for o2 in old2])  

new仍未完成:最后一步:

现在列出元素不在 old1 old2,创建临时列表tl

>>> tl=filter(lambda x : x not in e_o1 or x not in e_o2 , set(e_o1) | set(e_o2)) 
>>> tl
[9, 10]

现在new列表中追加tl的元素作为列表

>>> filter(lambda x:  new.append([x]) ,tl)
[]
>>> new
[[1, 2], [3], [4, 5], [7], [8, 6], [9], [10]]  

但结果仍然与 Adrien Plisson 代码类似:

old1 = [[1,2],[3,4]]old2 = [[1,2],[5,6]],
它将产生[[1,2],[3],[4],[5],[6]]

【讨论】:

  • 你说得对,“最常见的”具有误导性。我想到的是一个新列表,其中包含旧列表中的所有元素,同时保留最大数量的旧列表片段(如 [3,4,5] 和 [4,5,7] 中的 [4,5]。由于 9 和 10 分别只出现在一个旧列表中,因此它们应该在新列表中显示为单独的项目:[9]、[10]。
  • @Luigi old 表示来自old1 ?
  • old 表示来自old1old2
  • 你也需要像set([1,2,3,4]) - set([2,5])这样的东西!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-17
  • 1970-01-01
  • 2014-11-13
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
相关资源
最近更新 更多