How to combine list of objects into list of tuples (matrix style) in Python?

Question:

Let’s say that I have a list of tuples `foo` (object, integer) and a list of objects `bar`. The length of each of these parent lists is variable. How do I combine them into a single list of tuples, wherein each tuple is a unique combination of elements from each of the two parent lists?

• Example 1:

``````foo = [(A, i)]
bar = [X, Y]
# missing magic
expected_result = [(A, i, X), (A, i, Y)]
``````
• Example 2:

``````foo = [(A, i), (B, j)]
bar = [X, Y]
# missing magic
expected_result = [(A, i, X), (A, i, Y), (B, j, X), (B, j, Y)]
``````
• Example 3:

``````foo = [(A, i), (B, j), (C, k)]
bar = [X, Y]
# missing magic
expected_result = [(A, i, X), (A, i, Y), (B, j, X), (B, j, Y), (C, k, X), (C, k, Y)]
``````
• Example 4:

``````foo = [(A, i), (B, j)]
bar = [X]
# missing magic
expected_result = [(A, i, X), (B, j, X)]
``````

Preferably, I’d like to do this in one line, if possible. The order of the resulting list is unimportant, but the order of the elements within the tuples of that list need to be predictable.

In addition to trying various solutions using `itertools.product` and `zip`, I also looked at the answers to other similar questions, but I was unable to find the solution to this problem.

You can use a list comprehension with nested loops, spreading the elements in `foo`:

``````[(*f, b) for f in foo for b in bar]
``````

Your case is indeed tricky, and `zip` or `itertools.product` do not do the job, since you want to concatenate a tuple and an element into a tuple with all elements.
In one line, you can use unpacking:

``````expected_result = [(*i, j) for i in foo for j in bar]
``````

Assuming, as in your example, that `foo` is a list of tuples and `bar` is a list of elements.

You can use the `product` function in the `itertools` library to do this a couple of different ways:

``````import itertools

foo = [("A", 1), ("B", 2)]
bar = ["X", "Y"]

# Iterating over the product generator with a for loop
magicOne = []
for d in itertools.product(foo, bar):
magicOne.append( (*d[0], d[1]) )

# Using a list comprehension
magicTwo = [ (*d[0], d[1]) for d in itertools.product(foo, bar) ]

print(magicOne)
print(magicTwo)
``````

Both of these print:
`[('A', 1, 'X'), ('B', 2, 'X')]`

Brief Explanation

The product function is part of the standard library and it gives you a cartesian product of whatever iterables you provide.

It returns a generator that you can then use in a loop context, such as within a `for` loop or a list comprehension.

This line: `(*d[0], d[1])` is key, as it unpacks the first item in the product (the tuple), and combines it with the second item in the product (the list item), and combines them together into a new tuple.

Note that I used strings and ints here to keep things self-contained, but this works just as well if you have objects called `A` and `B` etc… defined elsewhere and use:

``````foo = [(A, i), (B, j)]
bar = [X]
``````
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.