【Python基础】Python中的高效迭代库itertools,排列组合随便求

本文目录

一、模块概述

二、组合生成器

2.1 product

2.2 permutations

2.3 combinations

2.4 combinations_with_replacement

三、无限迭代器

3.1 count

3.2 cycle

3.3 repeat

四、有限迭代器

4.1 accumulate

4.2 chain

4.3 chain.from_iterable

4.4 compress

4.5 dropwhile

4.6 filterfalse

4.7 groupby

4.8 islice

4.9 starmap

4.10 takewhile

4.11 tee

4.12 zip_longest

五、总结

一、模块概述

Functional tools for creating and using iterators,为高效循环而创建迭代器的函数。本模块标准化了一个快速、高效利用内存的核心工具集,这些工具本身或组合都很有用。它们一起形成了“迭代器代数”,这使得在纯Python中有可能创建简洁又高效的专用工具。

permutations函数可以求序列的排列,combinations函数可以求序列的组合除了这两个函数外,itertools还有相当多的功能,它主要是提供迭代类的操作。

迭代器的特点是:惰性求值(Lazy evaluation),即只有当迭代至某个值时,它才会被计算,这个特点使得迭代器特别适合于遍历大文件或无限集合等,因为我们不用一次性将它们存储在内存中。itertools 模块提供的迭代器函数有以下几种类型:

组合生成器:序列的排列、组合,求序列的笛卡儿积等,比如product可以生成两个序列的笛卡尔积;

无限迭代器:生成一个无限序列,比如count函数能生成自然数序列 1, 2, 3, 4, ...

有限迭代器:接收一个或多个序列(sequence)作为参数,进行组合、分组和过滤等,比如chain函数,能组合多个序列

print(dir(itertools))['__doc__', '__loader__', '__name__', '__package__', '__spec__', '_grouper', '_tee', '_tee_dataobject', 'accumulate', 'chain', 'combinations', 'combinations_with_replacement', 'compress', 'count', 'cycle', 'dropwhile', 'filterfalse', 'groupby', 'islice', 'permutations', 'product', 'repeat', 'starmap', 'takewhile', 'tee',  'zip_longest']

总之该模块为Python为创建自定义迭代器提供了非常好用的模块——itertools。由itertools提供的工具通常都很快速而且节省内存。你可以利用这些组成部分去创建自己独有的迭代器以完成高效的循环

官方参考文档:https://docs.python.org/zh-cn/3/library/itertools.html

二、排列组合迭代器

迭代器

实参

结果

product()

p, q, ... [repeat=1]

笛卡尔积,相当于嵌套的for循环

permutations()

p[, r]

长度r元组,所有可能的排列,无重复元素

combinations()

p, r

长度r元组,有序,无重复元素

combinations_with_replacement()

p, r

长度r元组,有序,元素可重复

例子

结果

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

2.1 product

作用:用于求多个可迭代对象的笛卡尔积,它跟嵌套的 for 循环等价

语法:itertools.product(iter1, iter2, ... iterN, [repeat=1])

for each in itertools.product('ABCD', 'XY'):    print(each)('A', 'X')('A', 'Y')('B', 'X')('B', 'Y')('C', 'X')('C', 'Y')('D', 'X')('D', 'Y')for each in itertools.product('abc', repeat=2):    print (each)('a', 'a')('a', 'b')('a', 'c')('b', 'a')('b', 'b')('b', 'c')('c', 'a')('c', 'b')('c', 'c')

2.2 permutations

作用:返回长度为r的排列

语法:itertools.permutations(iteravle[,r])

  • iterable: 可迭代对象

  • r: 关键字参数, 新元素的长度, 默认为 None, 即为新元素的长度就是元素个数

将 iterable 中的元素以长度为 r 进行排列。每个排列组合生成一个元组并添加到新迭代器中。排列时,排列顺序是按照 iterable 中元素的顺序进行的。因此,未排序的 iterable 和已排序的 iterable 排列后的结果是不同的。

若 iterable 中有相同值的元素,但是它们的位置是不同的,排列时也就会会认为它们是不同的。注意: 排列即为数学上的排列,从 n 个元素中取出 m 个元素的无重复排列或直线排列。

for each in itertools.permutations('abc', 2): print (each)('a', 'b')('a', 'c')('b', 'a')('b', 'c')('c', 'a')('c', 'b')

2.3 combinations

作用:返回指定长度的组合

语法: itertools.combinations(iterable, r)

iterable: 可迭代对象r: 新元素的长度for each in itertools.combinations('abc', 2):    print (each)('a', 'b')('a', 'c')('b', 'c')将 iterable 中的元素以长度为 r 进行组合。每个排列组合生成一个元组并添加到新迭代器中。与 permutations() 函数基本一致,但是 combinations() 函数会过滤掉元素值一致的元组。'''相比于排列,组合会筛选掉元素值一样的元组'''list(itertools.combinations('ABC', 2))[('A', 'B'), ('A', 'C'), ('B', 'C')]'''排列对照组'''list(itertools.permutations('ABC', 2))[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]

2.4 combinations_with_replacement

作用:返回指定长度的组合,组合内元素可重复

语法:itertools.combinations_with_replacement(iterable, r)

  • iterable: 可迭代对象

  • r: 关键字参数, 新元素的长度, 默认为 None, 即为新元素的长度就是元素个数

for each in itertools.combinations_with_replacement('abc', 2): print (each)('a', 'a')('a', 'b')('a', 'c')('b', 'b')('b', 'c')('c', 'c')

三、无限迭代器

有三个无限迭代器,当你使用它们的时候,你要知道何时去跳出这个循环,不然你将陷入无限循环之中,在生产数字或者遍历事先不知道长度的数据时非常有用。

迭代器

实参

结果

示例

count()

start, [step]

start,start+step,start+2*step, ...

count(10) --> 10 11 12 13 14 ...

cycle()

p

p0, p1, ... plast, p0, p1, ...

cycle('ABCD') --> A B C D A B C D ...

repeat()

elem [,n]

elem, elem, elem, ... 重复无限次或n次

repeat(10, 3) --> 10 10 10

3.1 count()

作用:返回以start开始,step递增的序列,无限递增

语法:itertools.count(start=0,step=1)

for each in itertools.count(start=0, step=2):    print (each)12...100003'''小应用, 当取到第三个 A 时停止'''test_str = ''for i in itertools.cycle('ABC'):    test_str += i    if test_str.count('A') >= 3:        breakprint(test_str)# ABCABCA

3.2 cycle()

作用:将迭代器进行无限迭代

语法:itertools.cycle(iterable)

for each in itertools.cycle('ab'): print(each)ab...ba

3.3 repeat()

作用:不停的返回object对象,如果指定了times,则返回times次

语法:itertools.repeat(object,[,times])

for each in itertools.repeat('ab', 2):print(each)abab   

四、有限迭代器

迭代器

实参

结果

示例

accumulate()

p [,func]

p0, p0+p1, p0+p1+p2, ...

accumulate([1,2,3,4,5]) --> 1 3 6 10 15

chain()

p, q, ...

p0, p1, ... plast, q0, q1, ...

chain('ABC', 'DEF') --> A B C D E F

chain.from_iterable()

iterable

p0, p1, ... plast, q0, q1, ...

chain.from_iterable(['ABC', 'DEF']) --> A B C D E F

compress()

data, selectors

(d[0] if s[0]), (d[1] if s[1]), ...

compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F

dropwhile()

pred, seq

seq[n], seq[n+1], ... 从pred首次真值测试失败开始

dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1

filterfalse()

pred, seq

seq中pred(x)为假值的元素,x是seq中的元素。

filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8

groupby()

iterable[, key]

根据key(v)值分组的迭代器

islice()

seq, [start,] stop [, step]

seq[start:stop:step]中的元素

islice('ABCDEFG', 2, None) --> C D E F G

starmap()

func, seq

func(*seq[0]), func(*seq[1]), ...

starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000

takewhile()

pred, seq

seq[0], seq[1], ..., 直到pred真值测试失败

takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4

tee()

it, n

it1, it2, ... itn 将一个迭代器拆分为n个迭代器

zip_longest()

p, q, ...

(p[0], q[0]), (p[1], q[1]), ...

zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-

4.1 accumulate()

作用:创建一个迭代器,返回累积汇总值或其他双目运算函数的累积结果值(通过可选的 func 参数指定),,若传入 func,则按照 func 中的方法执行。

语法:itertools.accumulate(iterable[, func, *, initial=None])

  • iterable: 可迭代对象

  • func: 带有两个参数的函数, 可选参数,func 参数有几种用法。它可以被设为 min() 最终得到一个最小值,或者设为 max() 最终得到一个最大值,或设为 operator.mul() 最终得到一个乘积。摊销表可通过累加利息和支付款项得到。给iterable设置初始值并只将参数 func 设为累加总数可以对一阶 递归关系 建模。

  • initial: 关键字参数, 默认为 None, 若此参数传参, 则此参数作为 iterable 的第一个元素

'''默认情况, 返回累计汇总值'''list(itertools.accumulate([1, 2, 3, 4, 5]))[1, 3, 6, 10, 15]

'''方法修改为计算累计的乘积'''import operator #该模块输出一系列对应Python内部操作符的函数data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]list(itertools.accumulate(data, operator.mul)) [3, 12, 72, 144, 144, 1296, 0, 0, 0, 0]

'''方法修改为计算累计的最大值'''list(itertools.accumulate(data, max))[3, 4, 6, 6, 6, 9, 9, 9, 9, 9]

# Amortize a 5% loan of 1000 with 4 annual payments of 90cashflows = [1000, -90, -90, -90, -90]list(itertools.accumulate(cashflows, lambda bal, pmt: bal*1.05 + pmt))[1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]

#Chaotic recurrence relation #https://en.wikipedia.org/wiki/Logistic_maplogistic_map = lambda x, _: r * x * (1 - x)r = 3.8x0 = 0.4inputs = repeat(x0, 36) # only the initial value is used[format(x, '.2f') for x in accumulate(inputs, logistic_map)]['0.40', '0.91', '0.30', '0.81', '0.60', '0.92', '0.29', '0.79', '0.63', '0.88', '0.39', '0.90', '0.33', '0.84', '0.52', '0.95', '0.18', '0.57', '0.93', '0.25', '0.71', '0.79', '0.63', '0.88', '0.39', '0.91', '0.32', '0.83', '0.54', '0.95', '0.20', '0.60', '0.91', '0.30', '0.80', '0.60']

'''在迭代器起始位置添加一个元素, 方法不变, 返回累计汇总值'''list(itertools.accumulate([1, 2, 3, 4, 5], initial=100))# [100, 101, 103, 106, 110, 115]
'''在迭代器起始位置添加一个元素, 方法修改为计算累计的乘积'''list(itertools.accumulate([1, 2, 3, 4, 5], lambda x, y: x * y, initial=10))#[10, 10, 20, 60, 240, 1200]

4.2 chain()

作用:chain 接收多个可迭代对象作为参数,将它们『连接』起来,作为一个新的迭代器返回。

语法:chain(iterable1, iterable2, iterable3, ...)

list(itertools.chain([1, 2, 3], ('A', 'B', 'C'), {'一', '二', '三'}))[1, 2, 3, 'A', 'B', 'C', '二', '一', '三']list(itertools.chain( 'ABC', 'DEF'))['A', 'B', 'C', 'D', 'E', 'F']

4.3 chain.from_iterable

作用:与 itertools.chain() 函数类似,但是参数是一个可迭代对象,将这个可迭代对象中元素一一添加到新迭代器中,如果元素是一个可迭代对象,那么会将这个元素内的元素一一添加到新迭代器中。小编自己的理解就是迭代器降维。

语法:itertools.chain.from_iterable(iterable)

'''将二维迭代器降维'''temp = itertools.chain.from_iterable(['1', ['2', '3'], ('4', '5')])print(list(temp))# ['1', '2', '3', '4', '5']

'''只能降一层维度, 三维将至二维'''temp = itertools.chain.from_iterable(['1', ['2', '3'], ('4', ['5', '6'])])print(list(temp))# ['1', '2', '3', '4', ['5', '6']]

PS: 迭代器维度概念可以理解为,整个迭代器中的元素都不是迭代器类型的就是一维,迭代器中的元素有是迭代器的就是二维,迭代器中的元素有是迭代器的,然后这个迭代器中还有元素是迭代器的就是三维,依此类推。

4.4 compress

作用:创建一个迭代器,将 data 中经过 selectors 真值测试为 True 的元素保留。当两个可迭代对象中的某一个到达末尾时执行停止,返回最终结果。

语法:compress(data, selectors)

  • data: 可迭代对象, 包含所需的数据

  • selectors: 可迭代对象, 真值测试数据

for each in itertools.compress('abcd', [1, 0, 1, 0]):    print (each)ac'''只判断前三个元素, 并且索引值为 0 和 2 的元素会保留到新迭代器中并返回'''temp = itertools.compress(['A', 'B', 'C', 'D'], [1, 0, 1])list(temp)# ['A', 'C']

4.5 dropwhile

作用:直到predicate为真,就返回iterable剩下的数据, 否则drop掉

语法:itertools.dropwhile(predicate, iterable)

for each in itertools.dropwhile(lambda x: x<5, [2,1,6,8,2,1]): print(each)6821

4.6 filterfalse

作用:创建一个迭代器,仅保留 iterable 中在 predicate 计算中为 False 的元素。如果 predicate 传入的是 None,则相当于传入 bool,意思是做真值测试。

语法:itertools.filterfalse(predicate, iterable)

  • predicate: 只需要一个参数的函数

  • iterable: 可迭代对象

'''元素的值减2小于等于0的为True'''temp = itertools.filterfalse(lambda x: x - 2 <= 0, [1, 2, 0, 3, 1])print(list(temp))# [3]'''真值测试'''temp = itertools.filterfalse(None, [1, 2, 0, 3, 1])print(list(temp))# [0]

4.7 groupby

作用:返回一组(key,itera),key为iterable的值,itera为等于key的所有项

语法:itertools.groupby(iterable[,key])

for key, vale in itertools.groupby('aabbbc'): print( key, list(vale))a ['a', 'a']b ['b', 'b', 'b']c ['c']

4.8 islice

作用:相当于迭代器方式的切片操作

语法:itertools.islice(iterable, start,stop[,step])

for each in itertools.islice('abcdefg', 1, 4, 2):    print(each)   bd    

4.9 starmap()

作用:返回function(iter)的值,iter为iterable的元素

语法:itertools.starmap(function,iterable)

for each in itertools.starmap(lambda x, y: x * y, [(1, 2), (3, 4)]): print(each) 212

4.10 takewhile()

作用:创建一个迭代器,将 iterable 中的元素当作 function 的参数计算,与 dropwhile() 函数恰恰相反,当结果的布尔值为 True 时,其元素添加到新迭代器中, 直到有元素的计算结果为 False 时,此元素与之后的元素全部抛弃。

语法:itertools.takewhile(predicate,iterable)

for each in itertools.takewhile(lambda x: x < 5, [1, 3, 5, 6]):print(each)13    

4.11 tee

作用:从一个可迭代对象中分裂出 n 个独立的可迭代对象并返回。

语法:itertools.tee(iterable, n=2)

for i in itertools.tee([1, 2, 3, 4, 5, 6], 2): print(list(i))# [1, 2, 3, 4, 5, 6]# [1, 2, 3, 4, 5, 6]

4.12 zip_longest

作用:创建一个迭代器,从所有传入的可迭代对象中抽取一个元素,将它们组合成一个元组,然后添加到迭代器中。

语法:itertools.zip_longest(*iterables, fillvalue=None)

  • iterables: 一个或多个可迭代对象

  • fillvalue: 关键字参数, 填充值, 默认为 None

list(itertools.zip_longest('xyz', '123456', '小伍哥', fillvalue='*'))[('x', '1', '小'), ('y', '2', '伍'), ('z', '3', '哥'), ('*', '4', '*'), ('*', '5', '*'), ('*', '6', '*')]

五、总   结

迭代器(生成器)在Python中是一种很常用也很好用的数据结构,比起列表(list)来说,迭代器最大的优势就是延迟计算,按需使用,从而提高开发体验和运行效率,以至于在Python 3中map,filter等操作返回的不再是列表而是迭代器。而通过iter函数把列表对象转化为迭代器对象又有点多此一举,这时候我们今天的主角itertools就该上场了。

itertools中的函数大多是返回各种迭代器对象,其中很多函数的作用我们平时要写很多代码才能达到,而在运行效率上反而更低,大概就总结到这里,不过Python的各种语言特性和库还是要多用才能熟练,最终达到随手拈来的程度。

(0)

相关推荐

  • 第一次把 Python 的切片理解得如此透彻

    来源:Python猫 作者:豌豆花下猫 众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串.列表.元组-)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢? 切片(slice) ...

  • 算法创作|纸牌三角形

    问题描述A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算).要求每个边的和相等.下图就是一种排法(如有对齐问题,参看p1.png).A9 64   837 5 2这样的排法可 ...

  • 第39天: Python itertools 模块

    简介 在 Python 中,迭代器是一种非常好用的数据结构,其最大的优势就是延迟生成,按需使用,从而大大提高程序的运行效率.而 itertools 作为 Python 的内置模块,就为我们提供了一套非 ...

  • Python基础入门之常用库汇总!

    Python有很多第三方库,这是人尽皆知的事情,但Python到底有多少个库,我想很多人应该都不了解,这篇文章小编详细的介绍一下. Chardet,字符编码探测器,可以自动检测文本.网页.xml的编码 ...

  • Python中处理日期时间库的使用方法

    最近在搞一个项目,遇到时间处理相关的需求.真的是实战需求导致学习需求,于是百度谷歌了一番,常用的时间处理方法和函数整理出本文.用百分之20时间,学会解决时间问题百分之80的问题. 常用的库有time. ...

  • Python中使用Beautiful Soup库的超详细教程

    Python中使用Beautiful Soup库的超详细教程

  • python基础之JSON标准库

    一.序列化的一些简单概念 我们平常使用的python对象所进行的操作是在内存中,当程序关闭就会被清空,所以我们需要用一种合适的方法将这些数据保存下来. 为了将我们的数据进行永久存储,需要引入序列化(p ...

  • 《Python中神奇的第三方库:Faker》

    来自:CSDN,作者:南枝向暖北枝寒MA  链接: https://blog.csdn.net/mall_lucy/article/details/108655317 [导读]:开发项目的时,为了测试 ...

  • 诚之和:如何理解Python基础中的for循环语句

    如何理解Python基础中的for循环语句,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题. Python for循环可以遍历任何序列的项目 ...

  • 常用的Python数据可视化库!Python基础入门

    Python是一门非常优秀的编程语言,被广泛的应用于各个领域,它不仅简单.易懂.语法清晰,还拥有各种各样的库,让我们的工作更高效.更便捷.今天为大家分享8个Python库,有了它们之后,数据可视化超轻 ...

  • 零基础学python,看完这篇文章,你的python基础就差不多了!

    Python基础语法 1. 认识Python 1.1 Python 简介 Python 的创始人为吉多·范罗苏姆(Guido van Rossum). Python 的设计目标: 一门 简单直观的语言 ...

  • Python可以开发IOS吗?Python基础!

    在大家的印象中,Python是一门应用领域非常广泛的编程语言,可以说无所不能,那么Python可以开发IOS或安卓APP吗?我想很多人都好奇这个问题,接下来我们一起来看看. 当然可以,Python是可 ...