【问题标题】:Find common slices in two Python lists在两个 Python 列表中查找公共切片
【发布时间】:2013-02-18 21:49:17
【问题描述】:

我想在两个 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。

【问题讨论】:

  • 您真的想要返回的列表列表吗?
  • 不,没必要,我编辑了我的问题。谢谢。
  • @Someone:反对票是社区的一种说法,即读者通常更喜欢一些先前努力的证据,无论是在真正尝试解决问题的尝试中,还是在概述一些可能的潜在策略时用过。
  • @SomeoneMe - 实际上,我的反对意见是因为您的帖子缺少问题。 Stack Overflow 是一个问答网站。如果海报(如您)提供特定问题,则效果最佳。然后其他读者(比如我)会为这个问题提供可能的答案。这与其他站点不同,后者在问题解决方案或请求响应甚至主题讨论范式上运行。那么,你的问题是什么?

标签: python list slice


【解决方案1】:
>>> 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]]

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

【讨论】:

  • @GrijeshChauhan:我不确定我是否理解你的评论。这正是 OP 真正想要的 :-)
【解决方案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)获取开始和结束索引,因此在找到匹配项后,您可以在同一个 matcher 对象上调用 find_longest_match(),但调整参数以便您开始照顾上一场比赛。

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

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]]

【讨论】:

  • @F.J:谢谢。我接受了另一个答案,只是因为我(菜鸟)更容易理解它;-)
  • 我相信你已经知道了,difflib.SequenceMatcher 有很多包袱,这使得它不适合简单的问题,尤其是因为它的效率低下。顺便说一句,您实际上应该使用get_matching_blocks(),而不是循环使用find_longest_match
  • 是的,我实际上并没有太多地使用 difflib,但看到了一个序列匹配问题,它似乎适用。但是我想在大多数情况下,性能差异可以忽略不计。
猜你喜欢
  • 2020-10-24
  • 1970-01-01
  • 2015-05-31
  • 2012-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多