How do I iterate through two lists in parallel?
Python 3
for f, b in zip(foo, bar):
print(f, b)
zip
stops when the shorter of foo
or bar
stops.
In Python 3, zip
returns an iterator of tuples, like itertools.izip
in Python2. To get a list
of tuples, use list(zip(foo, bar))
. And to zip until both iterators are
exhausted, you would use
itertools.zip_longest.
Python 2
In Python 2, zip
returns a list of tuples. This is fine when foo
and bar
are not massive. If they are both massive then forming zip(foo,bar)
is an unnecessarily massive
temporary variable, and should be replaced by itertools.izip
oritertools.izip_longest
, which returns an iterator instead of a list.
import itertools
for f,b in itertools.izip(foo,bar):
print(f,b)
for f,b in itertools.izip_longest(foo,bar):
print(f,b)
izip
stops when either foo
or bar
is exhausted.izip_longest
stops when both foo
and bar
are exhausted.
When the shorter iterator(s) are exhausted, izip_longest
yields a tuple with None
in the position corresponding to that iterator. You can also set a different fillvalue
besides None
if you wish. See here for the full story.
Note also that zip
and its zip
-like brethen can accept an arbitrary number of iterables as arguments. For example,
for num, cheese, color in zip([1,2,3], ['manchego', 'stilton', 'brie'],
['red', 'blue', 'green']):
print('{} {} {}'.format(num, color, cheese))
prints
1 red manchego
2 blue stilton
3 green brie
Is there a better way to iterate over two lists, getting one element from each list for each iteration?
This is as pythonic as you can get:
for lat, long in zip(Latitudes, Longitudes):
print(lat, long)
Iterating over two lists one after another
This can be done with itertools.chain
:
import itertools
l1 = [1, 2, 3, 4]
l2 = [5, 6, 7, 8]
for i in itertools.chain(l1, l2):
print(i, end=" ")
Which will print:
1 2 3 4 5 6 7 8
As per the documentation, chain
does the following:
Make an iterator that returns elements from the first iterable until it is exhausted, then proceeds to the next iterable, until all of the iterables are exhausted.
If you have your lists in a list, itertools.chain.from_iterable
is available:
l = [l1, l2]
for i in itertools.chain.from_iterable(l):
print(i, end=" ")
Which yields the same result.
If you don't want to import a module for this, writing a function for it is pretty straight-forward:
def custom_chain(*it):
for iterab in it:
yield from iterab
This requires Python 3, for Python 2, just yield
them back using a loop:
def custom_chain(*it):
for iterab in it:
for val in iterab:
yield val
In addition to the previous, Python 3.5
with its extended unpacking generalizations, also allows unpacking in the list literal:
for i in [*l1, *l2]:
print(i, end=" ")
though this is slightly faster than l1 + l2
it still constructs a list which is then tossed; only go for it as a final solution.
Efficient way to iterate over two related ArrayLists?
The Answer by dreamcrash is correct: While your looping of a pair of arrays works, you should instead take advantage of Java as a OOP language by defining your own class.
Record
Defining such a class is even simpler in Java 16 with the new records feature. Write your class as a record when it’s main purpose is communicating data, transparently and immutably.
A record is very brief by default. The compiler implicitly creates the constructor, getters, equals
& hashCode
, and toString
. You need only declare the type and name of each member field.
record ColorNoun ( String color , String noun ) {}
Use a record like a conventional class. Instantiate with new
.
ColorNoun blueSky = new ColorNoun ( "Blue" , "Sky" ) ;
Note that a record can be declared locally within a method, or declared separately like a conventional class.
Iterate through three lists multiple times sequentially picking one element from a list in each iteration
You can iterate as such for the solution:
subjects=["Americans","Indians"]
verbs=["plays","watch"]
objects=["Baseball","cricket"]
for s in subjects:
for v in verbs:
for o in objects:
print(s,v,o+".")
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)
Iterating over multiple lists simultaneously in Python
You can use zip
and itertools.chain
like this:
from itertools import chain
first = [0, 1, 2, 3, 1, 5, 6, 7, 1, 2, 3, 5, 1, 1, 2, 3, 5, 6]
second = [
[(13, 12, 32), (11, 444, 25)],
[(312, 443, 12), (123, 4, 123)],
[(545, 541, 1), (561, 112, 560)]
]
zip(first, chain(*(chain(*second))))
UPDATE
def add(x, y):
return x + y
# Flatten the second list
second_flattened = list(chain(*(chain(*second))))
# There is probably a better way to achieve this
foo = [add(x, y) for x, y in zip(first, second_flattened)]
# If second is longer we should append unprocessed values
if len(second_flattened) > len(first):
foo += second_flattened[len(foo): ]
bar = [foo[i:i+3] for i in range(0, len(foo), 3)]
second = [bar[i:i+2] for i in range(0, len(foo) / 3, 2)]
How to iterate through list infinitely with +1 offset each loop
You can use a deque
which has a built-in and efficient rotate function (~O(1)):
>>> d = deque([0,1,2])
>>> for _ in range(10):
... print(*d)
... d.rotate(-1) # negative -> rotate to the left
...
0 1 2
1 2 0
2 0 1
0 1 2
1 2 0
2 0 1
0 1 2
1 2 0
2 0 1
0 1 2
What is the best way to iterate over multiple lists at once?
The usual way is to use zip()
:
for x, y in zip(a, b):
# x is from a, y is from b
This will stop when the shorter of the two iterables a
and b
is exhausted. Also worth noting: itertools.izip()
(Python 2 only) and itertools.izip_longest()
(itertools.zip_longest()
in Python 3).
Related Topics
Generate a Random Derangement of a List
Why Not Generate the Secret Key Every Time Flask Starts
Play an Animated Gif in Python with Tkinter
How Can One Continuously Generate and Track Several Random Objects with a Time Delay in Pygame
How to Check If a Value Exists in a Dictionary
How to Efficiently Calculate a Running Standard Deviation
How to Perform HTML Decoding/Encoding Using Python/Django
Convert Image from Pil to Opencv Format
Calculating Arithmetic Mean (One Type of Average) in Python
How to Dynamically Load a Python Class
Is There Any Simple Way to Benchmark Python Script
Dropping Infinite Values from Dataframes in Pandas
Python: Change the Scripts Working Directory to the Script's Own Directory
Differencebetween Using Loc and Using Just Square Brackets to Filter for Columns in Pandas/Python
How to Get All the Contiguous Substrings of a String in Python