acdr
acdr

Reputation: 4706

Looping through the elements of pairs of lists

I have a list of tuples, which in turn consist of two lists again. For example:

big_list = [
    (["A", "B", "C"], [1, 2]),
    (["X", "Y"], [9, 8, 7]),
    ]

I'd like to call some function on each combination of (letter, number). I currently have a big ugly set of three nested for loops, along these lines:

for (letters, numbers) in big_list:
    for letter in letters:
        for number in numbers:
            do_stuff(letter, number)

That is, I'd like do_stuff to be called once, for each combination of (letter, number) present in my list.

Is it feasible to collapse these three loops into one or two? Preferably in a way that isn't ugly and unPythonic?

Upvotes: 4

Views: 97

Answers (2)

tobias_k
tobias_k

Reputation: 82899

You could also combine itertools.product with starmap and chain.from_iterable:

from itertools import chain, starmap, product
for l, n in chain.from_iterable(starmap(product, big_list)):
    print(l, n)

Of course, whether that's more clear is a matter of opinion. Or just use a generator expression:

for l, n in (p for ls, ns in big_list for p in product(ls, ns)):
     print(l ,n)

Both ways, the result (as list) is [('A', 1), ('A', 2), ('B', 1), ('B', 2), ('C', 1), ('C', 2), ('X', 9), ('X', 8), ('X', 7), ('Y', 9), ('Y', 8), ('Y', 7)].

Upvotes: 1

Sam Chats
Sam Chats

Reputation: 2321

I think itertools may help:

import itertools

for (letters, numbers) in big_list:
    for (letter, number) in itertools.product(letters, numbers):
        do_stuff(letter, number)

This saves you a loop, so now you only have one nested loop to deal with. And I think it's bit more Pythonic.

Upvotes: 3

Related Questions