To iterate pairwise or processing elements in groups of two in Python we can:
We can use the following syntax to margin on a single axis column or row in Pandas:
(1) Indexing - s -> (s0, s1), (s2, s3)
for i in range(0, len(lst) - 1, 2):
print(lst[i], lst[i + 1])
(2) zip
and Slicing
for a, b in zip(lst[::2], lst[1::2]):
print(a, b)
(3) iter()
and zip()
- fastest
it = iter(lst)
for a, b in zip(it, it):
print(a, b)
(4) s -> (s0, s1), (s1, s2)
from itertools import pairwise
for a, b in pairwise(lst):
print(a, b)
Python provides multiple ways to achieve this, ranging from basic indexing to more advanced approaches using iterators and external libraries.
This article explores different techniques and benchmarks their performance.
1. Using Indexing (Basic Approach)
A simple way is to use a for
loop with a step size of 2
:
lst = [1, 2, 3, 4, 5, 6]
for i in range(0, len(lst) - 1, 2):
print(lst[i], lst[i + 1])
result:
1 2
3 4
5 6
Pros
- Simple and easy to understand.
- Flexible - works on any iterable of length ≥ 2.
Cons
- Requires explicit index handling.
- May raise an
IndexError
if the list has an odd number of elements. - In case of list mutation might and in unexpected behavior
2. Using zip
and Slicing
Another approach is to use zip()
with slicing to pair elements:
for a, b in zip(lst[::2], lst[1::2]):
print(a, b)
result:
1 2
3 4
5 6
Pros
- More Pythonic and avoids explicit indexing.
- No risk of out-of-bounds indexing.
Cons
- Creates two temporary lists due to slicing, increasing memory usage.
3. Using iter()
and zip()
- fastest
By using iter()
and zip()
, we can efficiently pair elements without extra memory overhead:
it = iter(lst)
for a, b in zip(it, it):
print(a, b)
result:
1 2
3 4
5 6
Pros
- No need for slicing or extra lists.
- Uses iterators efficiently, saving memory.
- Works on any iterable (e.g., generators, files).
Cons
- Slightly less intuitive for beginners.
4. Using itertools.pairwise()
Python 3.10 introduced itertools.pairwise()
, which simplifies this process:
from itertools import pairwise
for a, b in pairwise(lst):
print(a, b)
Note this time the result is different:
1 2
2 3
3 4
4 5
5 6
It will iterate over all pairs in this way:
s -> (s0, s1), (s1, s2), (s2, s3), ...
More info: itertools.pairwise(iterable)
Pros
- Cleanest and most Pythonic.
- Works with any iterable.
Cons
- Only available in Python 3.10+.
5. Using more_itertools.chunked()
If you're using the more-itertools
library, chunked()
offers a powerful way to split lists into fixed-size chunks:
from more_itertools import chunked
for a, b in chunked(lst, 2):
print(a, b)
Pros
- Works well for chunking lists into groups of any size.
Cons
- Requires an external library (
pip install more-itertools
). - If the list has an odd number of elements, the last tuple will be incomplete.
Performance Benchmark
Let's compare the performance of different methods using timeit
:
import timeit
from itertools import pairwise
lst = list(range(100_000))
def method_indexing():
for i in range(0, len(lst) - 1, 2):
_ = lst[i], lst[i + 1]
def method_zip_slicing():
for a, b in zip(lst[::2], lst[1::2]):
_ = a, b
def method_iter_zip():
it = iter(lst)
for a, b in zip(it, it):
_ = a, b
def method_pairwise():
for a, b in pairwise(lst):
_ = a, b
print("Indexing:", timeit.timeit(method_indexing, number=100))
print("Zip + Slicing:", timeit.timeit(method_zip_slicing, number=100))
print("Iter + Zip:", timeit.timeit(method_iter_zip, number=100))
print("Pairwise (Python 3.10+):", timeit.timeit(method_pairwise, number=100))
Benchmark Results (Example on 1,000,000 items, Python 3.12)
Method | Time (seconds) |
---|---|
Indexing | 3.78 |
Zip + Slicing | 3.95 |
Iter + Zip | 2.21 |
Pairwise (3.10+) | 6.53 |
Key Takeaways:
zip(iter(), iter())
is fastest for Python 3.9 and below.itertools.pairwise()
is nearly as fast and more readable (Python 3.10+).zip()
with slicing is slower due to extra memory allocation.
Conclusion
The best method depends on performance needs and readability:
- Use
zip(iter(), iter())
for efficiency (Python 3.9 and below). - Use
itertools.pairwise()
if on Python 3.10+. - Use basic indexing for simplicity in small scripts.