I would like an elegant pythonic way to cycle through a list while having variables that have access to the current item and the next item during the iteration process. This is one method I know of that just gives me the current variable.
from itertools import cycle
stuff = ['a', 'b', 'c', 'd']
print(stuff)
for curr_item in cycle(stuff):
print("current:", curr_item)
Output:
['a', 'b', 'c', 'd']
current: a
current: b
current: c
current: d
current: a
current: b
current: c
...
Looking for something that kinda looks like:
from itertools import cycle
stuff = ['a', 'b', 'c', 'd']
print(stuff)
for curr_item, next_item in MAGIC(stuff):
print("current:", curr_item)
print("next:", next_item)
Desired output:
['a', 'b', 'c', 'd']
current: a
next: b
current: b
next: c
current: c
next: d
current: d
next: a
current: a
next: b
current: b
next: c
current: c
next: d
...
CodePudding user response:
A solution could be leveraging tee() function as follows:
from itertools import cycle, tee
stuff = ['a', 'b', 'c', 'd']
curr_iter, next_iter= tee(cycle(stuff),2)
next(next_iter)
for curr_item, next_item in zip(curr_iter,next_iter):
print("current:", curr_item)
print("nex:", next_item)
FYI: shouldn't use next as a variable name since it is already being used as a function name.
CodePudding user response:
we can slightly modify the snippet from this description to make our iterator:
def cycle(itr):
l = len(itr)
saved = []
for i,element in enumerate(itr,1):
yield element,itr[i%l]
saved.append(element)
while saved:
for j,element in enumerate(saved,1):
yield element,saved[j%l]
for curr_item, next_item in cycle(stuff):
print("current:", curr_item)
print("next:", next_item)
>>> out
'''
current: a
next: b
current: b
next: c
current: c
next: d
current: d
next: a
current: a
next: b
current: b
next: c
current: c
next: d
current: d
next: a
...
or we can make our own (it also shows prev element as a small bonus):
from collections import deque
# supports thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.
def cycle(iterable):
itr = deque(iterable)
while itr:
yield itr[-1],itr[0],itr[1]
cur = itr.popleft()
itr.append(cur)
c = cycle('12345')
for _ in range(10):
print('previous: {}, current: {}, next: {}'.format(*next(c)))
>>> out
'''
previous: 5, current: 1, next: 2
previous: 1, current: 2, next: 3
previous: 2, current: 3, next: 4
previous: 3, current: 4, next: 5
previous: 4, current: 5, next: 1
previous: 5, current: 1, next: 2
previous: 1, current: 2, next: 3
previous: 2, current: 3, next: 4
previous: 3, current: 4, next: 5
previous: 4, current: 5, next: 1