【问题标题】:Find overlapping elements in a list of tuples?在元组列表中查找重叠元素?
【发布时间】:2018-05-09 14:29:57
【问题描述】:

根据我对交集函数的理解,它发现列表中的元素之间完全重叠。例如:

tup_1 = [(1,2,3),(4,5,6)]
tup_2 = [(4,5,6)]
ol_tup = set(tup_1).intersection(tup_2)
print ol_tup

会产生:

set([(4, 5, 6)])

但是,假设我的元组列表是这样设置的:

tup_1 = [(1,2,3),(4,5,5)]
tup_2 = [(4,5,6)]

tup_1 中的第二个元组和 tup_2 中的第一个元组的 2 个元素有重叠。如果我想用python返回这2个元组:(4,5,5)和(4,5,6),有没有比这个嵌套for循环更简单的方法(下)?

for single_tuple_1 in tup_1:
    for single_tuple_2 in tup_2:
        if single_tuple_1[0] == single_tuple_2[0] and single_tuple_1[1] == single_tuple_2[1]:
            print single_tuple_1,single_tuple_2

编辑:

对于这种情况,假设顺序很重要并假设元组包含 5 个元素:

tup_1 = [(1,2,3,4,5),(4,5,6,7,8),(11,12,13,14,15)]
tup_2 = [(1,2,3,4,8),(4,5,1,7,8),(11,12,13,14,-5)]

我想找到在各自的前 4 个元素中相互交叉的元组。所以结果应该是:

[(1,2,3,4,5),(1,2,3,4,8),(11,12,13,14,15),(11,12,13,14,-5)]

代码将如何更改以适应这种情况?

【问题讨论】:

  • tup_2 是否总是包含一个元组?
  • 如果元素与其他两个重叠怎么办?你会打印两对吗?在这种情况下,我认为没有比二次方更快的方法,即比较每一对。
  • 另外,元组中元素的位置重要吗?
  • 您是否总是想检查两个共同点?如果还有更多呢?
  • 以下解决方案之一有帮助吗?如果接受,请随意接受(左侧的绿色勾号),或要求澄清。

标签: python list for-loop tuples intersection


【解决方案1】:

如果您想返回所有“重叠”元组对,则无法比较所有对,即二次算法。但是您可以使用列表理解使代码更优雅一点,product 用于组合,zipsum 用于比较:

>>> tup_1 = [(1,2,3),(4,5,5),(7,8,9)]

>>> tup_2 = [(4,5,6),(0,5,5),(9,8,7)]

>>> [(a, b) for (a, b) in itertools.product(tup_1, tup_2)
...         if sum(1 for ai, bi in zip(a, b) if ai == bi) >= 2]
[((4, 5, 5), (4, 5, 6)), ((4, 5, 5), (0, 5, 5))]

注意:这将检查两个元组是否在至少两个位置具有相同的元素,即顺序很重要。如果顺序无关紧要,您可以将 ab 转换为 set 并检查它们的交集的大小,但这可能会因为重复数字而失败,即 (1,1,2)(1,1,3) 的交集只会是1 而不是2

如果你只想匹配前两个,或者前两个和后两个元素,你可以在一致的析取中比较元组的切片:

>>> [(a, b) for (a, b) in itertools.product(tup_1, tup_2)
...         if a[:2] == b[:2]]
[((4, 5, 5), (4, 5, 6))]

>>> [(a, b) for (a, b) in itertools.product(tup_1, tup_2)
...         if a[:2] == b[:2] or a[-2:] == b[-2:]]
[((4, 5, 5), (4, 5, 6)), ((4, 5, 5), (0, 5, 5))]

【讨论】:

  • 如果我只想匹配每个元组的前 2 个元素或每个元组的最后 2 个元素,我是否必须在 a/b、ai/bi 中添加索引括号,或者这些变量都不添加?
【解决方案2】:

这是使用列表推导的一种方式。书面逻辑检查至少 2 个元素的重叠。

请注意,如果没有重叠,您将只剩下tup_2 的一个元素,但这可以很容易地识别出来。

from itertools import chain

tup_1 = [(1,2,3),(4,5,5)]
tup_2 = [(4,5,6)]

y = sorted(tup_2[0])
res = [i for i in chain(tup_1, tup_2) if
       sum(i==j for i, j in zip(sorted(i), y)) > 1]

print res

[(4, 5, 5), (4, 5, 6)]

【讨论】:

  • 请注意,如果元组有重复的元素,使用set 可能会失败。
猜你喜欢
  • 1970-01-01
  • 2011-01-12
  • 2016-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 1970-01-01
相关资源
最近更新 更多