Construct Cartesian Product Tuple list – Python
The task of constructing the Cartesian product of tuple lists in Python involves iterating through multiple tuples and generating all possible ordered combinations of their elements. For example, given a list of tuples a = [(1, 2), (‘A’, ‘B’), (‘X’, ‘Y’)], the goal is to produce a list of all possible combinations, such as (1, ‘A’, ‘X’), (1, ‘A’, ‘Y’) and so on, covering every possible pairing of elements across the tuples.
Using itertools.product
itertools.product() is the most efficient way to compute the Cartesian product of tuple lists. It works by expanding the input tuples into all possible combinations using an iterator, making it highly efficient for large datasets. This approach avoids excessive memory usage and performs significantly faster than other methods.
from itertools import product
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = list(product(*a))
print(res)
from itertools import product
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = list(product(*a))
print(res)
Output
[(1, 'A', 'X'), (1, 'A', 'Y'), (1, 'B', 'X'), (1, 'B', 'Y'), (2, 'A', 'X'), (2, 'A', 'Y'), (2, 'B', 'X'), (2, 'B', 'Y')]
Explanation: list(product(*a)) computes the Cartesian product of the unpacked tuples in a using itertools.product() and converts the result res into a list.
Using list comprehension
List comprehension provides a concise and readable way to generate the Cartesian product of tuple lists. It constructs combinations using multiple nested loops in a single compact expression, making it an elegant but slightly less efficient solution compared to itertools.product(). It is best suited for smaller datasets due to its memory consumption.
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = [(i, j, k) for i in a[0] for j in a[1] for k in a[2]]
print(res)
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = [(i, j, k) for i in a[0] for j in a[1] for k in a[2]]
print(res)
Output
[(1, 'A', 'X'), (1, 'A', 'Y'), (1, 'B', 'X'), (1, 'B', 'Y'), (2, 'A', 'X'), (2, 'A', 'Y'), (2, 'B', 'X'), (2, 'B', 'Y')]
Explanation: list comprehension generate all possible combinations of elements from the tuples a[0], a[1] and a[2], storing them as tuples in the list res.
Using functools.reduce
functools.reduce() allows a functional programming approach to computing the Cartesian product. It recursively applies a lambda function to generate combinations, reducing the need for explicit loops. While this method can be concise, it is generally less efficient than itertools.product() and harder to read for larger datasets.
from functools import reduce
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = reduce(lambda acc, x: [(i + (j,)) for i in acc for j in x],a , [()])
print(res)
from functools import reduce
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = reduce(lambda acc, x: [(i + (j,)) for i in acc for j in x],a , [()])
print(res)
Output
[(1, 'A', 'X'), (1, 'A', 'Y'), (1, 'B', 'X'), (1, 'B', 'Y'), (2, 'A', 'X'), (2, 'A', 'Y'), (2, 'B', 'X'), (2, 'B', 'Y')]
Explanation: lambda function takes an accumulator acc and each tuple x from a and combines each element of acc with elements from x to form a new list of tuples.
Using loop
A traditional approach using nested loops can be used to generate the Cartesian product manually. This method is explicit and easy to understand, but it becomes impractical for a larger number of tuples since it requires manually handling multiple levels of iteration. It is less scalable and computationally expensive, making it the least efficient method.
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = []
for i in a[0]:
for j in a[1]:
for k in a[2]:
res.append((i, j, k))
print(res)
a = [(1, 2), ('A', 'B'), ('X', 'Y')]
res = []
for i in a[0]:
for j in a[1]:
for k in a[2]:
res.append((i, j, k))
print(res)
Output
[(1, 'A', 'X'), (1, 'A', 'Y'), (1, 'B', 'X'), (1, 'B', 'Y'), (2, 'A', 'X'), (2, 'A', 'Y'), (2, 'B', 'X'), (2, 'B', 'Y')]
Explanation: For loop iterates over each element in the first tuple a[0], the second tuple a[1] and the third tuple a[2] , creating a tuple (i, j, k) for every combination of elements. Each resulting tuple is then appended to the list res.