详解Python中的排列组合生成器

这篇具有很好参考价值的文章主要介绍了详解Python中的排列组合生成器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

详解Python中的排列组合生成器

在实际的开发场景中,经常需要遍历多个数组中的元素,将它们组合在一起使用。要取完所有可能的组合,最基本的方法是使用嵌套的循环,有多少个数组就嵌套多少层循环。嵌套循环是基本的原理,但不够简洁,Python中有更优雅的方式来实现这种功能。

在Python的内置模块 functools 中,提供了高阶类 product() ,用于实现多个可迭代对象(列表、字符串等)中元素的组合,返回可迭代对象中元素组合的笛卡尔积,效果相当于嵌套的循环。为了更直观地看出效果,下面用代码对比来看 product 的效果。

product 效果演示

# coding=utf-8
phone = ['iPhone', 'HuaWei', 'Mi']
number = [1, 2, 3]
color = ['白', '黑']
for p in phone:
    for n in number:
        for c in color:
            print(f'{p}{n}{c}', end='  ')

# 调用product实现元素组合,替代for循环
import itertools
for p, n, c in itertools.product(phone, number, color):
    print(f'{p}{n}{c}', end='  ')

Output:

iPhone1白  iPhone1黑  iPhone2白  iPhone2黑  iPhone3白  iPhone3黑  HuaWei1白  HuaWei1黑  HuaWei2白  HuaWei2黑  HuaWei3白  HuaWei3黑  Mi1白  Mi1黑  Mi2白  Mi2黑  Mi3白  Mi3黑  
iPhone1白  iPhone1黑  iPhone2白  iPhone2黑  iPhone3白  iPhone3黑  HuaWei1白  HuaWei1黑  HuaWei2白  HuaWei2黑  HuaWei3白  HuaWei3黑  Mi1白  Mi1黑  Mi2白  Mi2黑  Mi3白  Mi3黑 

可以看到,实现相同的功能,for循环使用了三层嵌套,而 product() 只需要一层循环。

product 的结果是生成器,生成器中的每个元素是一个元组,可以直接遍历,也可以遍历时解包取出元组中的数据,还可以与列表推导式配合使用等。

product 用法介绍

在源码中,对 product 的描述是:Cartesian product of input iterables. Equivalent to nested for-loops. 翻译成中文:求输入可迭代对象的笛卡尔积,相当于嵌套的for循环。解释一下这句话,第一,product 的输入要是可迭代对象,如字符串、列表、元组等。第二,product 会将可迭代对象中的元素按笛卡尔积进行组合,相当于嵌套的循环。

如果不知道笛卡尔积是什么?这里简单介绍一下。笛卡尔积(Cartesian product)是指数学中将两个集合 X 和 Y 中的对象组合,第一个对象是 X 中的成员而第二个对象是 Y 中的成员,组合完所有可能的有序对。笛卡尔积又称为直积,表示为 X×Y 。例如,假设集合 X={a, b} ,集合 Y={0, 1, 2} ,则两个集合的笛卡尔积为 {(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)} 。

product 类就是专门为求笛卡尔积而量身定做的,用途一致,命名也一致(英文单词一样,见名知意)。

product 使用时可以传入多个可迭代对象,结果会求所有可迭代对象累加的笛卡尔积。product 还有一个 repeat 参数,repeat 用于设置 product() 中每个可迭代对象的重复次数,默认值为1。如果只传入一个可迭代对象,求自身的笛卡尔积,可以使用 repeat 参数指定重复多少次。例如,product(X, Y, repeat=2) 与 product(X, Y, X, Y) 相同,product(X, repeat=4) 与 product(X, X, X, X) 相同。

X = [1, 2]
Y = ['a', 'b']
itertools.product(X, repeat=4)
for combination in itertools.product(X, Y, X, Y):
    print(combination, end=' ')
    
print()
# 使用repeat参数设置重复次数
for combination in itertools.product(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') 

更多排列组合生成器及对比

在内置模块 functools 中,用于将多个可迭代对象中的元素排列组合的类不只 product ,还有三个类提供了类似的功能,共同组成了一组非常有用的高阶工具。下面依次介绍它们并进行对比。

permutations(iterable[, r]): Return successive r-length permutations of elements in the iterable. 返回可迭代对象中元素的长度为 r 的排列,元素不能重复。

combinations(iterable, r): Return successive r-length combinations of elements in the iterable. 返回可迭代对象中元素的长度为 r 的组合,元素不能重复。

combinations_with_replacement(iterable, r): Return successive r-length combinations of elements in the iterable allowing individual elements to have successive repeats. 返回可迭代对象中元素的长度为 r 的组合,允许元素重复。

product 是求笛卡尔积,permutations 是求排列,combinations 是求组合,combinations_with_replacement 是求组合但允许元素重复。它们分别是什么结果?相互之间有什么区别呢?通过下面的代码可以进行对比。

# 笛卡尔积
for p in itertools.product('ABCD', repeat=2):
    print(p, end=' ')

print('\n', '-'*20)
# 排列
for pe in itertools.permutations('ABCD', 2):
    print(pe, end=' ')

print('\n', '-'*20)
# 组合
for c in itertools.combinations('ABCD', 2):
    print(c, end=' ')

print('\n', '-'*20)
# 组合,元素可以重复
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') 

四个生成器返回的结果中都是元组,为了更直观地对比效果,将结果整理如下:

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 与 product 对比,比 product 少了元素相同的情况,从可迭代对象中取出 r 个元素,元素顺序相反属于不同情况,结果中会保留。 combinations 与 permutations 对比,combinations 中元素顺序相反的结果属于相同情况,结果中不重复保留,也就是说 combinations (组合)是无序的, permutations (排列)是有序的。combinations_with_replacement 与 combinations 对比,combinations_with_replacement 中允许相同元素重复被取,结果中多了两个元素相同的情况。

这三个类的参数都有且只有一个可迭代对象,不能同时传入多个可迭代对象。另一个参数 r 是从可迭代对象中选取 r 个元素来排列组合,permutations 的 r 不是必传参数,默认为可迭代对象的长度,permutations 和 combinations 的结果中不允许元素重复,所以 r 大于可迭代对象长度时结果为空,combinations_with_replacement 的结果允许元素重复,r 可以大于可迭代对象长度。

总结

1.四个生成器的用法和区别已经介绍完,它们相当于工具箱中的一组高级工具,可以根据不同的场景选用,提高代码的优雅性。

2.在一些特殊场景,我们知道要用多层循环嵌套,但是循环的嵌套层数是动态的,导致无法下手写循环代码,此时可以巧妙地用 product 解决问题。这点后面我会在实际的问题中说明。

参考文档:
[1] Python文档标准库functools:https://docs.python.org/2/library/itertools.html#


相关阅读:

Python中的@cache有什么妙用?

📢欢迎 点赞👍 收藏⭐ 评论📝 关注 如有错误敬请指正!

☟ 学Python,点击下方名片关注我。☟文章来源地址https://www.toymoban.com/news/detail-495611.html

到了这里,关于详解Python中的排列组合生成器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python小姿势 - ## Python中的迭代器与生成器

    Python中的迭代器与生成器 在Python中,迭代是一个非常重要的概念,迭代器和生成器是迭代的两种最常见的形式。那么,迭代器与生成器有何不同呢? 首先,我们先来了解一下迭代器。 迭代器是一种对象,它可以记住遍历的位置,并在每次访问时返回下一个元素。迭代器只能

    2024年02月04日
    浏览(58)
  • Python中的列表生成式(List Comprehensions)和列表生成器(Generator)

    Python中的列表生成式(List Comprehensions)和列表生成器(Generator),是Python提供的两个高级应用机制。 生成式是一种简写机制,坚持了龟叔的“Python要简单优雅”的设计理念。 生成器虽然翻译成中文以后只有一字之差,但是实现的机制和生成式已经完全不同了。它存储的是一个

    2024年02月05日
    浏览(54)
  • Python教程(26)——Python迭代器和生成器详解

    Python中的迭代器是一种对象,它可以迭代(遍历)一个可迭代对象(比如列表、元组或字符串)的元素。迭代器用于实现迭代器协议,即包含 __iter__() 方法和 __next__() 方法。 迭代器的工作原理是每次调用 __next__() 方法时返回可迭代对象的下一个元素,当没有元素可迭代时,抛

    2024年02月19日
    浏览(45)
  • python3 生成器与生成器表达式

    在 Python3 中,生成器表达式是一种语言结构,它可以快速地创建一个可迭代对象。生成器表达式类似于列表推导式,但使用圆括号而不是方括号,并且返回的是一个生成器对象而不是一个列表。 在 Python3 中,生成器表达式有两种类型:生成器函数和生成器表达式。 生成器函

    2024年02月02日
    浏览(87)
  • 【沐风老师】3DMAX宇宙生成器(一键生成星系)插件使用方法详解

    3DMAX宇宙生成器(一键生成星系)插件  3DMAX宇宙生成器(一键生成星系)插件,用于模拟星团及星系的运动。可以创建单个集合进行动画计算,也可以输入不同坐标,建立多个集合后统一进行动画计算。 【安装方法】 无需安装,使用时直接拖动插件文件到3dMax视口打开即可

    2024年02月08日
    浏览(47)
  • JavaScript 生成器函数详解:优雅处理异步任务流

    目录 1. 生成器函数的定义和使用 2. 暂停和恢复执行 3. 与其他语言特性的配合使用 Iterator Protocol 迭代器协议  解构赋值  生成器和 Promise 的组合使用          使用 Promise:         使用 async/await: 委托给另外一个Generator函数         Generators 是 JavaScript 中的一种

    2024年02月12日
    浏览(55)
  • Python 生成器推导

    生成器理解是在 python 中创建生成器的一种聪明而有效的方法。 它是定义生成器的单行规范,对于理解该语法以高效编码至关重要。 在本文中,我们将学习 python 的生成器和生成器理解以及示例。 Python 中的生成器是返回可迭代或遍历对象的函数,用于创建一次遍历项目的迭

    2024年02月09日
    浏览(65)
  • Python 实现卡密生成(卡密生成器)

    最近我在做一个基于 openCv2 的脚本,顺手写了一个卡密生成器,也给自己保存一下代码。 代码部分 接下来是下载连接,因为比较小就用某云盘了,知道的它下载一直很慢,其实也不算小Python打包出来的东西还是挺大的,压缩包里有一个ui文件不要删,那个是动态加载进的Qt文

    2024年02月21日
    浏览(59)
  • 实现高性能ID生成器:详解Java雪花算法

    Java中的雪花算法(Snowflake Algorithm)是一种用于生成唯一ID的算法,可以在分布式系统环境中防止ID重复。这种算法最初由Twitter开发,用于生成Twitter的唯一ID,由于其简单易懂和高效,已成为目前最常用的生成唯一ID的算法之一。 雪花算法生成的ID是一个64位的长整型数字,可

    2023年04月27日
    浏览(38)
  • python生成器generator的用法

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以

    2024年02月04日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包