Решения до сих пор имеют дело только со списками, и большинство копирует список. По моему опыту, много раз это было невозможно.
Кроме того, они не связаны с тем фактом, что в списке могут быть повторяющиеся элементы.
В заголовке вашего вопроса написано " Предыдущее и следующее значения внутри цикла ", но если вы выполните большинство ответов здесь внутри цикла, вы в конечном итоге будете повторять весь список снова для каждого элемента найти его.
Итак, я только что создал функцию. используя модуль itertools
, разбивает и разбивает итерируемое и генерирует кортежи с предыдущими и последующими элементами вместе. Не совсем то, что делает ваш код, но на это стоит взглянуть, потому что это, вероятно, решит вашу проблему.
from itertools import tee, islice, chain, izip
def previous_and_next(some_iterable):
prevs, items, nexts = tee(some_iterable, 3)
prevs = chain([None], prevs)
nexts = chain(islice(nexts, 1, None), [None])
return izip(prevs, items, nexts)
Затем используйте его в цикле, и у вас будут предыдущие и следующие элементы:
mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']
for previous, item, nxt in previous_and_next(mylist):
print "Item is now", item, "next is", nxt, "previous is", previous
Результаты:
Item is now banana next is orange previous is None
Item is now orange next is apple previous is banana
Item is now apple next is kiwi previous is orange
Item is now kiwi next is tomato previous is apple
Item is now tomato next is None previous is kiwi
Он будет работать с любым списком размеров (потому что он не копирует список) и с любыми повторяемыми (файлами, наборами и т. Д.). Таким образом, вы можете просто перебирать последовательность и иметь в цикле предыдущий и следующий элементы. Нет необходимости снова искать элемент в последовательности.
Краткое объяснение кода:
tee
используется для эффективного создания 3 независимых итераторов над входной последовательностью
chain
связывает две последовательности в одну; здесь он используется для добавления одноэлементной последовательности [None]
к prevs
islice
используется для создания последовательности всех элементов, кроме первого, затем chain
используется для добавления None
к его концу
- Теперь есть 3 независимых последовательности на основе
some_iterable
, которые выглядят следующим образом:
prevs
: None, A, B, C, D, E
items
: A, B, C, D, E
nexts
: B, C, D, E, None
- наконец
izip
используется для изменения 3 последовательностей в одну последовательность триплетов.
Обратите внимание, что izip
останавливается, когда исчерпывается любая входная последовательность, поэтому последний элемент prevs
будет игнорироваться, что правильно - нет такого элемента, что последним элементом был бы его prev
. Мы могли бы попытаться удалить последние элементы из prevs
, но поведение izip
делает это избыточным
Также обратите внимание, что tee
, izip
, islice
и chain
происходят из модуля itertools
; они работают на своих входных последовательностях «на лету» (лениво), что делает их эффективными и не вызывает необходимости иметь всю последовательность в памяти сразу в любое время.
В python 3
при импорте izip
будет отображаться ошибка, вместо izip
можно использовать zip
. Нет необходимости импортировать zip
, это предопределено в python 3
- source