До сих пор решения касались только списков, и большинство из них копирует список. По моему опыту, во многих случаях это невозможно.
Кроме того, они не учитывают тот факт, что в списке могут быть повторяющиеся элементы.
В заголовке вашего вопроса написано « Предыдущее и следующее значения внутри цикла », но если вы запустите большинство ответов здесь внутри цикла, вам придется снова перебирать весь список для каждого элемента, чтобы найти его.
Итак, я только что создал функцию, которая. с помощью 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
- finally
izipиспользуется для преобразования 3 последовательностей в одну последовательность триплетов.
Обратите внимание, что izipостанавливается, когда любая входная последовательность исчерпана, поэтому последний элемент prevsбудет проигнорирован, что правильно - нет такого элемента, который был бы последним элементом prev. Мы могли бы попытаться удалить последние элементы из, prevsно izipповедение делает это избыточным
Также отметим , что tee, izip, isliceи chainисходить от itertoolsмодуля; они оперируют своими входными последовательностями на лету (лениво), что делает их эффективными и не требует одновременного хранения всей последовательности в памяти в любое время.
В python 3, он покажет ошибку при импорте izip, вы можете использовать zipвместо izip. Нет необходимости импорта zip, он не предопределены python 3- источник