我想在两个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。
答案 0 :(得分:2)
>>> 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]]
但请记住,这比以前的线性解决方案效率低得多