在两个Python列表中查找常见切片

时间:2013-03-04 17:52:02

标签: python list slice

我想在两个Python列表中找到常见的切片。

例如:

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

list2 = [0, 0, 3, 4, 5, 0, 0, 8, 9, 0]

应返回两个列表: [3,4,5]和[8,9]

可以有任何数字或字符代替0。

2 个答案:

答案 0 :(得分:2)

使用difflib.SequenceMatcher

>>> import difflib
>>> list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list2 = [0, 0, 3, 4, 5, 0, 0, 8, 9, 0]
>>> matcher = difflib.SequenceMatcher(a=list1, b=list2)
>>> match = matcher.find_longest_match(0, len(list1), 0, len(list2))
>>> match
Match(a=2, b=2, size=3)
>>> print list1[match.a:match.a+match.size]
[3, 4, 5]

SequenceMatcher.find_longest_match()获取每个序列的开始和结束索引(alo,ahi,blo,bhi),因此在找到匹配后,您可以在同一个find_longest_match()对象上调用matcher但调整参数,以便开始照看上一场比赛。

你可以循环执行此操作,我会编写一个函数来执行此操作,如下所示:

import difflib
def common_slices(a, b):
    matcher = difflib.SequenceMatcher(a=a, b=b)
    sa, sb, size = matcher.find_longest_match(0, len(a), 0, len(b))
    while size != 0:
        if size > 1:
            yield a[sa:sa+size]
        sa, sb, size = matcher.find_longest_match(sa+size, len(a), sb+size, len(b))

>>> list(common_slices(list1, list2))
[[3, 4, 5], [8, 9]]

答案 1 :(得分:2)

>>> from itertools import groupby
>>> from operator import itemgetter
>>> list1
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list2
[0, 0, 3, 4, 5, 0, 0, 8, 9, 0]
>>> [[e[0] for e in v]
     for k,v in groupby(((a ,b, a==b)
             for a,b in zip(list1, list2)), itemgetter(2))
      if k]
[[3, 4, 5], [8, 9]]

如果您想要使用@ F.J。建议的difflib,您应该以这种方式使用

>>> [list1[match.a: match.a + match.size]
     for match in SequenceMatcher(None,list1,list2).get_matching_blocks()[:-1]]

但请记住,这比以前的线性解决方案效率低得多

相关问题