简体   繁体   English

在列表中查找连续值

[英]Finding consecutive values within a list

I have a list of values: 我有一个值列表:

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

I now want the following function: 我现在想要以下功能:

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

So the values must be found in consecutive order. 因此,必须按连续顺序找到这些值。

I there a clever way of doing this in Python 3? 我有在Python 3中执行此操作的聪明方法吗?

You can use a rolling window iterator, in this case one from an old version of the itertools docs: 您可以使用滚动窗口迭代器,在这种情况下,它来自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]))

If you only need it to work on lists, not any iterable, you can use: 如果只需要它来处理列表,而不需要迭代,则可以使用:

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

A basic implementation of the method mentioned by 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]))

The advantage of this method is that it doesn't have to slice for every index up to the first match, just for indexes corresponding to matches for the first value in the segment. 此方法的优点是,不必为直到第一个匹配项的每个索引切片,而只需对与该段中第一个值的匹配项对应的索引进行切片。

There are many ways to do this and they are all isomorphic to substring search algorithms . 有很多方法可以做到这一点,它们对于子串搜索算法都是同构的。

The easiest way is the naïve search using list.index() to find a common start point and then using a slice to check for a full match. 最简单的方法是使用list.index()来天真的搜索,以找到一个共同的起点,然后使用切片来检查完全匹配。 If there is not a match, repeat the search until you hit the end of the list. 如果没有匹配项,请重复搜索,直到到达列表末尾。

This should work with Python 2.5 and newer: 这适用于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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM