itertools.product() is a part of a python module itertools; a collection of tools used to handle iterators. Together all these tools form iterator algebra. Itertools will make your code stand out. Above all, it will make it more pythonic.
One would question the need for itertools. They are faster and much more memory efficient.
The itertools are of the following types:
- Infinite iterators
- Terminating iterators
- Combinatoric iterators
Although the itertools library contains many valuable functions, we will discuss the itertools.product() method of combinatoric iterators, you can check out the other methods from here.
Decoding the itertools.product() Method
This method of itertools determines the cartesian product of two sets(here list).
Cartesion product
The collection of all ordered pairs of two given sets (here list) such that the first elements of the pairs are chosen from one set and the second element from the other set.
A × B = {(a, b) : a ∈ A and b ∈ B}
Import
import itertools
# or can directly import
from itertools import product
Syntax & Parameters
Syntax:
itertools.product(*iterables, repeat)
Parameters:
- Iterables: Iterable are objects which generate an iterator. For instance, common python iterable are list, tuple, string, dictionaries.
- Repeat: It is an optional parameter and accepts whole numbers as value. When used it returns the cartesion product of the iterable with itself for the number of times specified in repeat parameter.
Return type
It returns an iterator which can be iterated over to get individual values one at a time.
Time complexity
The time complexity for itertools.product() is O(m*n), where m and n are the sizes of the two lists.
The itertools.product() Hackerrank problem
Problem Statement
The above problem requires you to find the cartesian product of two lists provided separately through input. Given below is a simple solution using the product() method.
Let’s briefly discuss the steps involved:
- the map functions takes in the inputs of the list A and B (read question provided in the link above) and store them into list1 and list2 respectively.
- then we take the cartesian product of the list1 and list2 using the product() method of itertools.
- at last we iterate over the cart_product to print out the tuples of cartesian product.
from itertools import product
list1 = list(map(int,input().split()))
list2 = list(map(int,input().split()))
cart_product = product(list1,list2)
for item in cart_product:
print(item,end=" ")
itertools.product() to list
One can very quickly convert iterator by using the list() function.
import iterools
list_A = [1,2,3]
list_B = [4,5,6]
iter_to_list = list(itertools.product.(list_A, list_B))
print(iter_to_list)
Another unique way to replicate the above example is to use the * operator to unpack the values:
ite = itertools.product.(list_A, list_B)
iter_to_list = [*ite]
print(iter_to_list)
Replacing for loop by using itertools
In addition, the product() method can be used instead of for loop; it is concise and much faster.
Let’s briefly discuss the code below:
- We have imported the time library, to measure the speed of executions of itertools product() method and for loop.
- In the first iteration of the for loop i = 1, j = 4 and k = 7, it exhausts the list3 for values of k 8 & 9. Then it sets j = 5 and repeats the steps.
- In the second iteration of the for loop i = 2, j = 4 and k = 7, it exhausts the list3 for values of k 8 & 9. Then it sets j = 5 and repeats the steps. This is similarly repeated for i = 3.
- s1, s2 denote the starting time of itertools product() method and for loop executions repectively, similarly e1 , e2 denote end times. e1 – s1 and e2 – s2 give the running times of product() method and for loop.
import time
import itertools
list1 = [1,2,3]
list2 = [4,5,6]
list3 = [7,8,9]
s1 = time.time()
iter_list = itertools.product(list1,list2,list3)
e1 = time.time()
print("Output for itertools.product()")
print(list(iter_list))
list_new = []
s2 = time.time()
for i in list1:
for j in list2:
for k in list3:
list_new.append((i,j,k))
e2 = time.time()
print("Output for FOR loop")
print(list_new)
print(f"Time for itertools.product():{e1-s1}")
print(f"Time for regular for loop:{e2-s2}")
Python itertools product() with conditions
We can add conditions to the product() method with the filter function. For instance, given below example filters only the tuples starting with an even number.
Let’s briefly discuss the code below:
- Python’s filter function takes in a ‘function’ and an ‘iterable’ , it filters out the results according to the conditions of the function.
- product() method has repeat set to 4, what it does is; it return all the ways to arrange the vals numbers where repeats are allowed.
- Then lambda function filters out the tuples starting with an even number.
from itertools import product
vals = [1,2,3,4]
values = filter(lambda vals:int(vals[0]) % 2 == 0,product(vals,repeat=4))
print(list(values))
Generating dataframe using itertools.product()
You can generate dataframes using the method and apply a function to generate column/s.
Let’s briefly discuss the code below:
- In order to generate a dataframe from itertools product() method, we have specified a lambda function.
- Here lambda function ‘func’ takes the ‘i’ and ‘j’ values of the cartesian product of lists a & b and adds them.
- Values generated through ‘func’ results in third column of the dataframe.
- Similarly, you can create multiple columns for your dataframe.
from pprint import pprint
a = [1,2,3]
b = [4,5,6]
func = lambda i, j: i+j
result = [(i, j, func(i,j)) for i, j in itertools.product(a, b)]
pprint(result)
FAQs on Python itertools Products
One might find a couple zip and product() methods of itertools together as both return iterators however they are miles apart. The zip function couples respective elements of lists while the product() follows the cartesian product rule.list_A = [1,2,3]
list_B = [4,5,6]
print(zip(list_A,list_B)
print(list(itertools.product(list_A,list_B))
itertools product() method can be used instead of for loop. It is much faster has minimum code clutter. Since itertools product() method gives an iterator which only returns value one by one; only if called upon.
Conclusion
In conclusion, itertools.product() makes our code efficient, concise, and pythonic. Although we only discussed the product() method in this blog, many other methods will make your code look cleaner and run faster.