我正在寻找解决此问题的最有效内存的方法。
我有一个元组列表,表示句子中的部分字符串匹配:
[(0, 2), (1, 2), (0, 4), (2,6), (23, 2), (22, 6), (26, 2), (26, 2), (26, 2)]
每个元组的第一个值是匹配的起始位置,第二个值是长度。
想法是折叠列表,以便仅报告最长的继续字符串匹配。在这种情况下,它将是:
[(0,4), (2,6), (22,6)]
我不想要最长的范围,例如algorithm to find longest non-overlapping sequences,但我希望所有范围都折叠最长。
如果你想知道,我正在使用Aho-Corasick的纯python实现来将静态字典中的术语与给定的文本片段进行匹配。
编辑:由于这些元组列表的性质,应单独打印重叠但不是自包含的范围。例如,在字典中使用单词betaz
和zeta
,betazeta
的匹配为[(0,5),(4,8)]
。由于这些范围重叠,但没有一个包含在另一个中,答案应该是[(0,5),(4,8)]
。我还修改了上面的输入数据集,以便涵盖这种情况。
谢谢!
答案 0 :(得分:4)
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)]
答案 1 :(得分:1)
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)]
答案 2 :(得分:-1)
所以,带上你的话,你的主要兴趣是空间效率,这是你想做的事情的一种方式:
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))
这会修改列表到位,永远不会使列表更长,只使用少量变量来保持状态,只需要一次通过列表
如果您不想在适当的位置修改列表,则可以使用更快的算法 - 从列表中间弹出项目可能会很慢,尤其是在列表很长的情况下。
一个合理的优化是保留一个列表,列出你要删除的索引,然后返回并在第二遍中重建列表,这样你就可以一次性重建整个列表并避免{ {1}}开销。但那会占用更多的内存!