将范围元组列表折叠到重叠范围中



我正在寻找解决此问题的最节省内存的方法。

我有一个表示句子中部分字符串匹配的元组列表:

[(0, 2), (1, 2), (0, 4), (2,6), (23, 2), (22, 6), (26, 2), (26, 2), (26, 2)]

每个元组的第一个值是匹配的起始位置,第二个值是长度。

这个想法是折叠列表,以便只报告最长的继续字符串匹配。在这种情况下,它将是:

[(0,4), (2,6), (22,6)]

我不希望只有最长的范围,就像在算法中查找最长的非重叠序列一样,但我希望所有范围都折叠最长的范围。

如果您想知道,我正在使用 Aho-Corasick 的纯 python 实现,用于将静态字典中的术语与给定的文本片段进行匹配。

编辑:由于这些元组列表的性质,应单独打印出重叠但不是独立的范围。例如,在字典中betazzeta单词,betazeta的匹配项[(0,5),(4,8)]。由于这些范围重叠,但没有包含在另一个范围中,因此答案应该是 [(0,5),(4,8)] .我还修改了上面的输入数据集,以便涵盖这种情况。

谢谢!

import operator
lst = [(0, 2), (1, 2), (0, 4), (2,6), (23, 2), (22, 6), (26, 2), (26, 2), (26, 2)]
lst.sort(key=operator.itemgetter(1))
for i in reversed(xrange(len(lst)-1)):
    start, length = lst[i]
    for j in xrange(i+1, len(lst)):
        lstart, llength = lst[j]
        if start >= lstart and start + length <= lstart + llength:
            del lst[i]
            break
print lst
#[(0, 4), (2, 6), (22, 6)]
a = [(0, 2), (1, 2), (0, 4), (23, 2), (22, 6), (26, 2), (26, 2), (26, 2)]
b = [set(xrange(i, i + j)) for i, j in a]
c = b.pop().union(*b)
collapsed = sorted(c)
print collapsed
#Maybe this is useful?:
[0, 1, 2, 3, 22, 23, 24, 25, 26, 27]
#But if you want the requested format, then do this:
d = []
start = collapsed[0]
length = 0
for val in collapsed:
    if start + length < val:
        d.append((start,length))
        start = val
        length = 0
    elif val == collapsed[-1]:
        d.append((start,length + 1))
    length += 1
print d
#Output:
[(0,4), (22,6)]

因此,如果您相信自己的主要兴趣是空间效率,这里有一种方法可以做您想做的事情:

lst = [(0, 2), (1, 2), (0, 4), (23, 2), (22, 6), (26, 2), (26, 2), (26, 2)]
lst.sort()
start, length = lst.pop(0)
i = 0
while i < len(lst):
    x, l = lst[i]
    if start + length < x:
        lst[i] = (start, length)
        i += 1
        start, length = x, l
    else:
        length = max(length, x + l - start)
        lst.pop(i)
lst.append((start, length))

这会就地修改列表,从不使列表更长,只使用少量变量来保持状态,并且只需要通过列表进行一次传递

如果您不想就地修改列表,则可以使用更快的算法 - 从列表中间弹出项目可能会很慢,尤其是在列表很长的情况下。

一个合理的优化是保留要删除的索引的列表,然后在第二遍中返回并重建列表,这样您就可以一次性重建整个列表并避免pop开销。 但这会占用更多内存!

最新更新