Python进阶编程:编写更高效、优雅的Python代码
上QQ阅读APP看书,第一时间看更新

4.1.7 排列组合的迭代

涉及科学计算时,做排列组合是一个很常见的操作。如对于实现迭代遍历一个集合中元素的所有可能的排列组合的需求,我们可以使用itertools模块中相关的函数。itertools模块提供了3个函数解决这类问题。其中一个是itertools.permutations()函数,它可以实现接收一个集合并产生一个元组序列,每个元组由集合中所有元素的一个可能的排列组成。通过打乱集合中元素排列顺序生成一个元组,代码(comb_iter.py)示例如下:


item_list = ['a', 'b', 'c']
from itertools import permutations
for p in permutations(item_list):
    print(f'all permutations is: {p}')

执行py文件,输出结果如下:


all permutations is: ('a', 'b', 'c')
all permutations is: ('a', 'c', 'b')
all permutations is: ('b', 'a', 'c')
all permutations is: ('b', 'c', 'a')
all permutations is: ('c', 'a', 'b')
all permutations is: ('c', 'b', 'a')

如果想得到指定长度的所有排列,可以传递一个可选的长度参数,代码(comb_iter.py)示例如下:


for p in permutations(item_list, 2):
    print(f'permutations 2 is: {p}')

执行py文件,输出结果如下:


permutations 2 is: ('a', 'b')
permutations 2 is: ('a', 'c')
permutations 2 is: ('b', 'a')
permutations 2 is: ('b', 'c')
permutations 2 is: ('c', 'a')
permutations 2 is: ('c', 'b')

使用itertools.combinations()函数可以得到输入集合中元素的所有的排列组合,代码(comb_iter.py)示例如下:


from itertools import combinations
for c in combinations(item_list, 3):
    print(f'combinations 3 is: {c}')

for c in combinations(item_list, 2):
    print(f'combinations 2 is: {c}')

for c in combinations(item_list, 1):
    print(f'combinations 1 is: {c}')

执行py文件,输出结果如下:


combinations 3 is: ('a', 'b', 'c')
combinations 2 is: ('a', 'b')
combinations 2 is: ('a', 'c')
combinations 2 is: ('b', 'c')
combinations 1 is: ('a',)
combinations 1 is: ('b',)
combinations 1 is: ('c',)

对于combinations()函数来讲,元素的顺序不重要。组合('a','b')与('b','a')是一样的(最终只会输出其中一个)。

在计算组合的时候,一旦元素被选取就会从候选中剔除掉(比如,如果元素a已经被选取,那么接下来排列组合时就不会再考虑它了)。

函数itertools.combinations_with_replacement()允许同一个元素被选择多次,代码(comb_iter.py)示例如下:


from itertools import combinations_with_replacement
for c in combinations_with_replacement(item_list, 3):
    print(f'combinations with replacement is: {c}')

执行py文件,输出结果如下:


combinations with replacement is: ('a', 'a', 'a')
combinations with replacement is: ('a', 'a', 'b')
combinations with replacement is: ('a', 'a', 'c')
combinations with replacement is: ('a', 'b', 'b')
combinations with replacement is: ('a', 'b', 'c')
combinations with replacement is: ('a', 'c', 'c')
combinations with replacement is: ('b', 'b', 'b')
combinations with replacement is: ('b', 'b', 'c')
combinations with replacement is: ('b', 'c', 'c')
combinations with replacement is: ('c', 'c', 'c')

上述示例展示的仅仅是itertools模块的一部分功能。

尽管自己可以手动实现排列组合,但是这样做效率低。当遇到比较复杂的迭代问题时,最好可以先选择使用itertools模块中的函数解决。