【问题标题】:Finding consecutive values within a list在列表中查找连续值
【发布时间】:2011-11-01 15:36:03
【问题描述】:

我有一个值列表:

a = [1,3,4,5,2]

我现在想要以下功能:

does_segment_exist(a, [1,3,4]) #True
does_segment_exist(a, [3,4,5]) #True
does_segment_exist(a, [4,5,2]) #True
does_segment_exist(a, [1,4,5]) #False
does_segment_exist(a, [1,3]) #True
does_segment_exist(a, [1,4]) #False

所以这些值必须以连续的顺序找到。

我在 Python 3 中有一个聪明的方法吗?

【问题讨论】:

标签: python list python-3.x


【解决方案1】:

您可以使用滚动窗口迭代器,在本例中是来自旧版本的 itertools 文档:

from itertools import islice

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result
    for elem in it:
        result = result[1:] + (elem,)
        yield result

def does_segment_exist(iterable, sublist):
    return tuple(sublist) in window(iterable, len(sublist))

print(does_segment_exist([1,3,4,5,2], [3,4,5]))

如果您只需要它在列表上工作,而不是任何可迭代的,您可以使用:

def does_segment_exist(seq, sublist):
    # seq and sublist must both be lists
    n = len(sublist)
    return sublist in (seq[i:i+n] for i in range(len(seq) + 1 - n))

Raymond提到的方法的基本实现:

def does_segment_exist(seq, sublist):
    first = sublist[0]
    i = 0
    n = len(sublist)
    while True:
        try:
            i = seq.index(first, i)
        except ValueError:
            return False
        if sublist == seq[i:i+n]:
            return True
        i += 1

print(does_segment_exist([1,3,4,5,2], [3,4,5]))

这种方法的优点是它不必对每个索引进行切片,直到第一个匹配项,只需对与段中第一个值的匹配项对应的索引进行切片。

【讨论】:

    【解决方案2】:

    有很多方法可以做到这一点,它们都与substring search algorithms 同构。

    最简单的方法是使用 list.index() 进行简单搜索以找到一个公共起点,然后使用切片检查是否完全匹配。如果没有匹配项,请重复搜索,直到找到列表的末尾。

    【讨论】:

    • >>> help(list.index) 关于method_descriptor的帮助:index(...) L.index(value, [start, [stop]]) -> integer -- 返回第一个索引价值。如果值不存在,则引发 ValueError。
    • 文档的标准类型页面上未显示的任何特殊原因?
    • 为文档更新提交错误跟踪报告。它可能被忽略了(在某一时刻,并非所有序列都有 index())。
    【解决方案3】:

    这应该适用于 Python 2.5 和更新版本:

    def does_segment_exist(sequence, segment):
        n, m = len(sequence), len(segment)
        return any(segment == sequence[i:i+m] for i in range(n+1-m))
    

    【讨论】:

    • 如果你看我的第二个,它是一样的——短路切片比较。 in 只是自动执行==
    • 抱歉,忽略了这一点。是的,本质上是一样的,应该没有明显的性能差异。
    • 实际上,您使用“in”的解决方案看起来更加优雅,并且适用于较旧的 Python 版本。
    猜你喜欢
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2014-11-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 2013-04-25
    相关资源
    最近更新 更多