SoFunction
Updated on 2024-11-19

About permutation generators in Python in detail

permutation generator

In real-world development scenarios, it is often necessary to iterate through the elements of multiple arrays to combine them for use. The most basic way to fetch all possible combinations is to use nested loops, with as many layers of loops as there are arrays. Nested loops are the basic principle, but are not concise enough; there are more elegant ways to accomplish this in Python.

Python's built-in module functools provides a high-level class, product(), which implements the combination of elements from multiple iterable objects (lists, strings, etc.) and returns the Cartesian product of the combinations of the elements in the iterable objects, which is equivalent to a nested loop. In order to visualize the effect, here is a code comparison to see the effect of product.

product demo

# coding=utf-8
phone = ['iPhone', 'HuaWei', 'Mi']
number = [1, 2, 3]
color = ['White', 'Black']
for p in phone:
    for n in number:
        for c in color:
            print(f'{p}{n}{c}', end='  ')
# Call product to implement element combining instead of for loops
import itertools
for p, n, c in (phone, number, color):
    print(f'{p}{n}{c}', end='  ')

Output:

iPhone1 white iPhone1 black iPhone2 white iPhone2 black iPhone3 white iPhone3 black HuaWei1 white HuaWei1 black HuaWei2 white HuaWei2 black HuaWei3 white HuaWei3 black Mi1 white Mi1 black Mi2 white Mi2 black Mi3 white Mi3 black
iPhone1 white iPhone1 black iPhone2 white iPhone2 black iPhone3 white iPhone3 black HuaWei1 white HuaWei1 black HuaWei2 white HuaWei2 black HuaWei3 white HuaWei3 black Mi1 white Mi1 black Mi2 white Mi2 black Mi3 white Mi3 black

As you can see, the for loop uses three levels of nesting to achieve the same functionality, while product() requires only one level of looping.

The result of product is a generator, each element in the generator is a tuple, which can be traversed directly, or unpacked when traversing to take out the data in the tuple, and can also be used in conjunction with list derivatives, and so on.

How to use product

In the source code, the description of product is: Cartesian product of input iterables. Equivalent to nested for-loops.

Explain this statement.

First, the input to the product must be an iterable object, such as a string, a list, a tuple, etc. The input to the product must be an iterable object, such as a string, a list, or a tuple.

Second, product combines the elements of an iterable object by Cartesian product, which is equivalent to a nested loop.

If you don't know what the Cartesian product is? Here's a brief introduction. Cartesian product is the mathematical combination of two sets X and Y, where the first object is a member of X and the second object is a member of Y, in all possible ordered pairs. The Cartesian product, also known as the direct product, is denoted X × Y . For example, suppose set X = {a, b} and set Y = {0, 1, 2}, then the Cartesian product of the two sets is {(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}.

The product class is tailor-made for finding the Cartesian product, with the same purpose and the same name (the same English word, see name).

product can be passed multiple iterables and the result will be the Cartesian product of all the iterables. product also has a repeat parameter, repeat, which is used to set the number of repetitions for each of the iterables in product(), and defaults to 1. If you pass in only one iterable to find its own Cartesian product, you can specify how many times to repeat it with the repeat parameter to specify how many times to repeat. For example, product(X, Y, repeat=2) is the same as product(X, Y, X, Y), and product(X, repeat=4) is the same as product(X, X, X, X, X).

X = [1, 2]
Y = ['a', 'b']
(X, repeat=4)
for combination in (X, Y, X, Y):
    print(combination, end=' ')
print()
# Use the repeat parameter to set the number of repetitions
for combination in (X, Y, repeat=2):
    print(combination, end=' ')

Output:

(1, 'a', 1, 'a') (1, 'a', 1, 'b') (1, 'a', 2, 'a') (1, 'a', 2, 'b') (1, 'b', 1, 'a') (1, 'b', 1, 'b') (1, 'b', 2, 'a') (1, 'b', 2, 'b') (2, 'a', 1, 'a') (2, 'a', 1, 'b') (2, 'a', 2, 'a') (2, 'a', 2, 'b') (2, 'b', 1, 'a') (2, 'b', 1, 'b') (2, 'b', 2, 'a') (2, 'b', 2, 'b') 
(1, 'a', 1, 'a') (1, 'a', 1, 'b') (1, 'a', 2, 'a') (1, 'a', 2, 'b') (1, 'b', 1, 'a') (1, 'b', 1, 'b') (1, 'b', 2, 'a') (1, 'b', 2, 'b') (2, 'a', 1, 'a') (2, 'a', 1, 'b') (2, 'a', 2, 'a') (2, 'a', 2, 'b') (2, 'b', 1, 'a') (2, 'b', 1, 'b') (2, 'b', 2, 'a') (2, 'b', 2, 'b') 

More permutation generators and comparisons

In the built-in module functools, product is not the only class used for arranging and combining elements in multiple iterable objects; there are three other classes that provide similar functionality, and together they form a very useful set of higher-order tools. They are described in turn and compared below.

permutations(iterable[, r]): Return successive r-length permutations of elements in the iterable. Returns the r-length permutations of elements in the iterable.

combinations(iterable, r): Return successive r-length combinations of elements in the iterable. Returns r-length combinations of elements in the iterable, elements cannot be repeated.

combinations_with_replacement(iterable, r): Return successive r-length combinations of elements in the iterable allowing individual elements to have successive repeats. Returns the length of the element in the iterable object as r combinatorial,Allow element repetition。

product is for Cartesian products, permutations is for permutations, combinations is for combinations, and combinations_with_replacement is for combinations but allowing elements to be repeated. What are their results? What is the difference between them? You can compare them with the following code.

# The Cartesian product
for p in ('ABCD', repeat=2):
    print(p, end=' ')
print('\n', '-'*20)
# Ranking
for pe in ('ABCD', 2):
    print(pe, end=' ')
print('\n', '-'*20)
# Combination
for c in ('ABCD', 2):
    print(c, end=' ')
print('\n', '-'*20)
# Combination, elements can be repeated
for cr in itertools.combinations_with_replacement('ABCD', 2):
    print(cr, end=' ')

Output:

('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') 
('B', 'A') ('B', 'B') ('B', 'C') ('B', 'D')
('C', 'A') ('C', 'B') ('C', 'C') ('C', 'D') 
('D', 'A') ('D', 'B') ('D', 'C') ('D', 'D') 
 --------------------
('A', 'B') ('A', 'C') ('A', 'D') 
('B', 'A') ('B', 'C') ('B', 'D') 
('C', 'A') ('C', 'B') ('C', 'D') 
('D', 'A') ('D', 'B') ('D', 'C') 
 --------------------
('A', 'B') ('A', 'C') ('A', 'D') 
('B', 'C') ('B', 'D') ('C', 'D') 
 --------------------
('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') 
('B', 'B') ('B', 'C') ('B', 'D') 
('C', 'C') ('C', 'D') ('D', 'D') 

All four generators return tuples in their results, and the results are organized as follows in order to compare the effects more visually:

product('ABCD', repeat=2)
AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD

permutations('ABCD', 2)
AB AC AD BA BC BD CA CB CD DA DB DC

combinations('ABCD', 2)
AB AC AD BC BD CD

combinations_with_replacement('ABCD', 2)
AA AB AC AD BB BC BD CC CD DD

permutations vs. product has fewer cases of identical elements than product, where r elements are taken from an iterable, and the opposite order of the elements is a different case that is retained in the result. combinations versus permutations, combinations with elements in the opposite order are the same, and are not repeated and retained in the result, i.e., combinations are unordered and permutations are ordered. combinations_with_ replacement In contrast to combinations, combinations_with_replacement allows the same elements to be fetched repeatedly, so that there are two more cases where the elements are the same in the result.

The parameters of these three classes have one and only one iterable object, you can't pass in more than one iterable object at the same time. Another parameter r is to select r elements from the iterable objects to arrange the combinations. r is not a mandatory parameter for permutations, it defaults to the length of the iterable objects, permutations and combinations don't allow duplication of elements in the result, so the result will be null if r is greater than the length of the iterable objects, combinations_with_replacement allows duplication of elements in the result, and r can be greater than the length of the iterable objects. and combinations do not allow duplication of elements in their results, so the result will be empty if r is greater than the length of the iterable object.

summarize

1. The usage and differences of the four generators have been introduced, they are equivalent to a set of advanced tools in the toolbox, which can be selected according to different scenarios to improve the elegance of the code.

2. In some special scenarios, we know that we need to use multiple nested loops, but the number of nested loops is dynamic, resulting in the inability to write the loop code, then you can cleverly use product to solve the problem. I will explain this point later in the actual problem.

To this article on the Python permutation generator in detail on this article, more related Python permutation generator content, please search my previous posts or continue to browse the following related articles I hope you will support me in the future more!