How can I iterate over overlapping (current, next) pairs of values from a list?
Here's a relevant example from the itertools module docs:
import itertools
def pairwise(iterable):
"s -> (s0, s1), (s1, s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
For Python 2, you need itertools.izip
instead of zip
:
import itertools
def pairwise(iterable):
"s -> (s0, s1), (s1, s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
How this works:
First, two parallel iterators, a
and b
are created (the tee()
call), both pointing to the first element of the original iterable. The second iterator, b
is moved 1 step forward (the next(b, None)
) call). At this point a
points to s0 and b
points to s1. Both a
and b
can traverse the original iterator independently - the izip function takes the two iterators and makes pairs of the returned elements, advancing both iterators at the same pace.
One caveat: the tee()
function produces two iterators that can advance independently of each other, but it comes at a cost. If one of the iterators advances further than the other, then tee()
needs to keep the consumed elements in memory until the second iterator comsumes them too (it cannot 'rewind' the original iterator). Here it doesn't matter because one iterator is only 1 step ahead of the other, but in general it's easy to use a lot of memory this way.
And since tee()
can take an n
parameter, this can also be used for more than two parallel iterators:
def threes(iterator):
"s -> (s0, s1, s2), (s1, s2, s3), (s2, s3, 4), ..."
a, b, c = itertools.tee(iterator, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)
Iterate over all pairs of consecutive items in a list
Just use zip
>>> l = [1, 7, 3, 5]
>>> for first, second in zip(l, l[1:]):
... print first, second
...
1 7
7 3
3 5
If you use Python 2 (not suggested) you might consider using the izip
function in itertools
for very long lists where you don't want to create a new list.
import itertools
for first, second in itertools.izip(l, l[1:]):
...
Iterate through pairs of items in a Python list
From the itertools
recipes:
from itertools import tee
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
for v, w in pairwise(a):
...
Iterate an array as a pair (current, next) in JavaScript
Just make the "ugly" part into a function and then it looks nice:
arr = [1, 2, 3, 4];
function pairwise(arr, func){
for(var i=0; i < arr.length - 1; i++){
func(arr[i], arr[i + 1])
}
}
pairwise(arr, function(current, next){
console.log(current, next)
})
You can even slightly modify it to be able to make iterate all i, i+n pairs, not just the next one:
function pairwise(arr, func, skips){
skips = skips || 1;
for(var i=0; i < arr.length - skips; i++){
func(arr[i], arr[i + skips])
}
}
pairwise([1, 2, 3, 4, 5, 6, 7], function(current,next){
console.log(current, next) // displays (1, 3), (2, 4), (3, 5) , (4, 6), (5, 7)
}, 2)
Using next () to iterate through a list of date values in Python
Is this what you want to do?
import datetime
listdates=[
datetime.date(2022, 2, 10),
datetime.date(2022, 2, 11),
datetime.date(2022, 2, 12),
datetime.date(2022, 2, 13),
datetime.date(2022, 2, 14)
]
for i in range(len(listdates)-1):
print(listdates[i],listdates[i+1])
Output:
2022-02-10 2022-02-11
2022-02-11 2022-02-12
2022-02-12 2022-02-13
2022-02-13 2022-02-14
Iterators are pointers to the elements of your list.
You cant use next
on the elements of the list - unless they are iterators themselves.
When you do for x in my_list
, x
is an element of the list, not an iterator.
That's why you are getting the error, the type date is not an iterator:
'datetime.date' object is not an iterator
This is valid:
l = [1,2,3,4]
my_iterator = iter(l)
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
This is not:
l = ['a','b','c','d']
a = l[0]
print(next(a))
how to pair each 2 elements of a list?
You have to increment iterator i.e by i
by 2 when moving forward
Category=[]
for i in range(0, len(attach), 2):
Category.append(f'{attach[i]},{attach[i+1]}')
Also, you don't need the if
condition, if the len(list)
is always even
Iterate through adjacent pairs in a generator
I would create a generator function to do this:
def adjacent_pairs(it):
it = iter(it)
a, b = next(it), next(it)
while True:
yield a, b
a, b = b, next(it)
Example usage:
def gen():
yield 5
yield 7
yield 11
yield 4
yield 5
for v, w in adjacent_pairs(gen()):
print [v, w]
Iterating over every two elements in a list
You need a pairwise()
(or grouped()
) implementation.
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return zip(a, a)
for x, y in pairwise(l):
print("%d + %d = %d" % (x, y, x + y))
Or, more generally:
def grouped(iterable, n):
"s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
return zip(*[iter(iterable)]*n)
for x, y in grouped(l, 2):
print("%d + %d = %d" % (x, y, x + y))
In Python 2, you should import izip
as a replacement for Python 3's built-in zip()
function.
All credit to martineau for his answer to my question, I have found this to be very efficient as it only iterates once over the list and does not create any unnecessary lists in the process.
N.B: This should not be confused with the pairwise
recipe in Python's own itertools
documentation, which yields s -> (s0, s1), (s1, s2), (s2, s3), ...
, as pointed out by @lazyr in the comments.
Little addition for those who would like to do type checking with mypy on Python 3:
from typing import Iterable, Tuple, TypeVar
T = TypeVar("T")
def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
"""s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
return zip(*[iter(iterable)] * n)
Related Topics
How to Input a Regex in String.Replace
How to Programmatically Set an Attribute
Why Does This Iterative List-Growing Code Give Indexerror: List Assignment Index Out of Range
How to Split a Text into Sentences
Multiple Prints on the Same Line in Python
Numpy or Pandas: Keeping Array Type as Integer While Having a Nan Value
Changing One List Unexpectedly Changes Another, Too
Pygame Doesn't Let Me Use Float For Rect.Move, But I Need It
How to Stop More Than 1 Bullet Firing At Once
Using Both Python 2.X and Python 3.X in Ipython Notebook
Python Exit Commands - Why So Many and When Should Each Be Used
Maximum and Minimum Values For Ints
How to Parallelize a Simple Python Loop
How to Convert Local Time String to Utc
How to Query as Group by in Django
Scatter Plot With Different Text At Each Data Point