我有一个元组列表,需要删除每个具有与其他元组重叠的整数值的元组

I have a list of tuples and need to drop each one that has integer values that overlaps other tuple

我有一个元组列表,每个元组中有两个整数和一个字符串。 我需要生成一个新列表,删除整数范围在其他元组内重叠的元组。

我试过这个:


list_all = [(0, 3, 'textA'), (0, 5, 'textB'), (8, 11, 'textC')]

empty_list = []

for i in list_all:
  range_i = list( range(list_all[i][0], list_all[i][1]) )
  
  for j in list_all:
    range_j = list( range(list_all[j][0], list_all[j][1]) )
    
    if  all( item in range_j for item in range_i ) == False:
      empty_list.append(range_i)

empty_list

但是我收到了这个错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-233-b4cebb65d49c> in <module>()
      4 
      5 for i in list_all:
----> 6   range_i = list( range(list_all[i][0], list_all[i][1]) )
      7 
      8   for j in list_all:

TypeError: list indices must be integers or slices, not tuple

你得到那个错误是因为 i 指向一个元组,而不是索引(因为你写的是 for i in list_all: 而不是 for i in range(len(list_all))

至于手头的任务,您是想只保留不与任何东西重叠的间隔,还是想保留不重叠的最大间隔数列表?例如,如果有 3 个范围 A、B、C,其中 A 和 C 与 B 重叠,但 A 不与 C 重叠,您要 return [A,C] 还是 []?

如果我没理解错的话,你只想保留与其他元组有重叠范围的最大范围的元组。您可以使用集合比较运算符 < 来检查一个范围是否在另一个范围内。请注意 set(a) < set(b) 实际上意味着 set(a)set(b) 的子集而不等于 set(b).

这是您问题的单行代码:

list_all = [(0, 3, 'textA'), (0, 5, 'textB'), (8, 11, 'textC')]

res = [t for t in list_all if not any(set((range(t[0], t[1]))) < set(r)
       for r in [range(i, j) for (i, j, _) in list_all])]
print(res)

输出:

[(0, 5, 'textB'), (8, 11, 'textC')]

思路是先获取所有范围,然后select只获取范围集不小于任何其他元组范围集的元组。

当然你也可以写成

res = [t for t in list_all if all(set((range(t[0], t[1]))) > set(r)
       for r in [range(i, j) for (i, j, _) in list_all])]

这是我的代码的固定版本(感谢 Eric Cartman)。我意识到我需要的是一个没有 ex 的列表。 (0, 3, 'textA'), 因为0-3与0-5重叠.


list_all = [(0, 3, 'textA'), (0, 5, 'textB'), (8, 11, 'textC'), (20, 25, 'textD')]

empty_list = []

for i in range(len(list_all)):
  range_i = list( range(list_all[i][0], list_all[i][1]) )
  
  for j in range(len(list_all)):
    range_j = list( range(list_all[j][0], list_all[j][1]) )
    
    if  all( item in range_j for item in range_i ) == False:
      empty_list.append(list_all[i])


empty_list

我有这个输出,我几乎有,但我正在生成重复项:

'''
[(0, 3, 'textA'),
 (0, 3, 'textA'),
 (0, 5, 'textB'),
 (0, 5, 'textB'),
 (0, 5, 'textB'),
 (8, 11, 'textC'),
 (8, 11, 'textC'),
 (8, 11, 'textC'),
 (20, 25, 'textD'),
 (20, 25, 'textD'),
 (20, 25, 'textD')]
'''