Поиск последовательных значений в списке

1

У меня есть список значений:

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?

Теги:
list
python-3.x

3 ответа

4
Лучший ответ

Вы можете использовать итератор с катящимся окном, в этом случае один из старой версии itertools docs:

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

Основная реализация метода, упомянутого Раймондом:

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

Преимущество этого метода заключается в том, что ему не нужно срезать для каждого индекса до первого совпадения только для индексов, соответствующих совпадениям для первого значения в сегменте.

1

Существует много способов сделать это, и они все изоморфны алгоритма поиска подстроки.

Самый простой способ - наивный поиск с помощью list.index(), чтобы найти общую начальную точку, а затем использовать срез для проверки полного соответствия. Если нет совпадения, повторите поиск, пока не попадете в конец списка.

  • 0
    >>> help (list.index) Справка по method_descriptor: index (...) L.index (value, [start, [stop]]) -> integer - вернуть первый индекс значения. Вызывает ValueError, если значение отсутствует.
  • 0
    Есть какая-то конкретная причина, которая не указана на странице стандартных типов документов?
Показать ещё 1 комментарий
1

Это должно работать с 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))
  • 0
    Если вы посмотрите на мою вторую, это то же самое - сравнение коротких замыканий. in только что автоматически делает == .
  • 0
    Извините, упустил это. Да, это по сути то же самое, и не должно быть заметных различий в производительности.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню