我正在研究一个NLP项目,并且我有一个列表,其中某些字符包含字符跨度。 该列表可能如下所示:
[(1,4),(1,7),(4,9),(8,15)]
所以我的任务是返回所有非重叠对。
如果两个或更多数字对重叠,则应返回跨度最长的数字对。在我的示例中,我想返回[(1,7),(8,15)]
。我该怎么办?
编辑
我不想像Merge overlap here中那样合并我的间隔。但是我不会返回所有对/间隔/元组,除非某些元组中的值重叠。例如(1,4)和(1,7)重叠,(4,9)与(1,4)和(1,7)重叠。如果有一些重叠,我想返回跨度最大的元组,例如(1,7)=跨度7,(1,4)=跨度4,(4,9)=跨度5。这意味着它也应返回(1,7)和(8,15),因为(8, 15)不重叠(1,7)
答案 0 :(得分:1)
对此考虑不多,但是以下方法可以解决问题:
spans = [(1,4),(1,7),(4,9),(8,15)]
del_in = []
for x in spans:
if spans.index(x) in del_in: continue
for y in spans:
if spans.index(y) in del_in: continue
if x == y: continue
if len(set(list(range(x[0],x[1]+1))) & set(list(range(y[0],y[1]+1)))) > 0:
if len(list(range(x[0],x[1]+1))) > len(list(range(y[0],y[1]+1))):
del_in.append(spans.index(y))
spans.pop(spans.index(y))
elif len(list(range(y[0],y[1]+1))) > len(list(range(x[0],x[1]+1))):
del_in.append(spans.index(x))
spans.pop(spans.index(x))
print(spans)
将输出:
[(1, 7), (8, 15)]
简短说明:
我们开始遍历跨度列表(迭代x
)。对于每个元组,我们再次遍历列表(迭代y
),而忽略x
(if x == y: continue
)中的元组。然后,我们用(1,4)
将每个元组转换成一个列表(例如,从[1, 2, 3, 4]
到list(range())
),并比较列表(尽可能与set()
),以查看它们中是否包含任何元素共同。如果返回的对象的长度大于0,我们将比较两个列表的长度,以查看保留的是哪一个(跨度较大的列表)。随后,我们从列表中删除跨度较小的项目(使用.pop()
)。由于我们的迭代x
和y
仍然遍历我们的初始列表,因此我们需要实现一种机制,以防止脚本比较已删除条目的项目。因此,我们使用一个附加列表,其中包含已经删除的条目的模具索引(并将它们留在两个for循环中)。
也许有更好的方法来执行此操作,但这绝对适用于您的示例。