python-itertools
python-itertools
概要
迭代器的最大好处就是按需使用,延迟计算,可以储存无限大的数列,当迭代到到某一个值的时候,才会计算得出这个值,从而提高程序的运行效率,降低内存的消耗。
Python 提供了可以创建高效循环的迭代器 itertools
主要分为三类,无限迭代器,有限迭代器,组合迭代器
无限迭代器
就是一个计数器,可以指定起始位置和步长
函数 | 说明 | 结果说明 | |
---|---|---|---|
itertools.count(start=0,step=1) | 从指定的数值开始,和指定的步长,返回一个迭代器 | count(10) --> 10 11 12 13 14 ... | |
itertools.cycle(Iterator) | 循环迭代器 | cycle('ABCD') --> A B C D A B C D ... | |
itertools.repeat(elem [,n]) | 重复无限次或n次 | repeat(10, 3) --> 10 10 10 |
itertools.count
结果返回:start, start+step, start+2*step, …
import itertools
for i in itertools.count(10,2):
print(i)
if i>20:
break
#----------------------------------
#如果没有,break 则会一直迭代下去
10
12
14
16
18
20
22
x = itertools.count(start=20, step=-1)
print(list(itertools.islice(x, 0, 10, 1)))
# [20, 19, 18, 17, 16, 15, 14, 13, 12, 11]
itertools.cycle
循环指定的列表和迭代器
x = itertools.cycle('ABC')
print(list(itertools.islice(x, 0, 10, 1)))
['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A']
itertools.repeat
- 生成一个指定数目,指定重复元素的的迭代器
x = itertools.repeat(0, 5)
print(list(x))
# [0, 0, 0, 0, 0]
x = itertools.repeat([1,2], 3)
print(list(x))
# [[1, 2], [1, 2], [1, 2]]
x = itertools.repeat("12", 5)
print(list(x))
# ['12', '12', '12', '12', '12']
有限迭代器
接收一个或多个序列(sequence)作为参数,进行组合、分组和过滤等
函数 | 说明 | 结果说明 | |
---|---|---|---|
accumulate(p,func) | p0, p0+p1, p0+p1+p2, ... | accumulate([1,2,3,4,5]) --> 1 3 6 10 15 | |
chain(Iterator) | 连接多个列表或者迭代器。 | chain('ABC', 'DEF') --> A B C D E F | |
chain.from_iterable() | 对一个迭代对象 | chain.from_iterable(['ABC', 'DEF']) --> A B C D E F | |
compress() | 根据真值表进行元素筛选 | compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F | |
dropwhile() | 条件为False之后的第一次,就返回迭代器中剩余的所有项 | dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1 | |
filterfalse() | filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8 | ||
groupby() | 根据key(v)值分组的迭代器 | ||
islice() | 设定一个特定的切片 | islice('ABCDEFG', 2, None) --> C D E F G | |
starmap() | 类似于map |
starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000 | |
takewhile() | 和dropwhile刚好相反,只要predicate计算后为False,迭代过程立刻停止 | takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4 | |
zip_longest() | zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- |
itertools.accumulate
累加器
import itertools
x = itertools.accumulate(range(10))
print(list(x))
# [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
itertools.chain
chain 接收多个可迭代对象作为参数, 连接多个列表或者迭代器。chain(iterable1, iterable2, iterable3, ...)
x = itertools.chain(range(3), range(4), [3,2,1])
print(list(x))
# [0, 1, 2, 0, 1, 2, 3, 3, 2, 1]
chain.from_iterable
作用:与 itertools.chain() 函数类似,但是参数是一个可迭代对象,将这个可迭代对象中元素一一添加到新迭代器中,如果元素是一个可迭代对象,那么会将这个元素内的元素一一添加到新迭代器中
'''将二维迭代器降维'''
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']]
itertools.compress
创建一个迭代器,将 data 中经过 selectors 真值测试为 True 的元素保留
按照真值表筛选元素
语法:compress(data, selectors)
x = itertools.compress(range(5), (True, False, True, True, False))
print(list(x))
# [0, 2, 3]
'''只判断前三个元素, 并且索引值为 0 和 2 的元素会保留到新迭代器中并返回'''
temp = itertools.compress(['A', 'B', 'C', 'D'], [1, 0, 1])
list(temp)
# ['A', 'C']
itertools.dropwhile
直到predicate为真,就返回iterable剩下的数据, 否则drop掉
按照真值函数丢弃掉列表和迭代器前面的元素
for each in itertools.dropwhile(lambda x: x<5, [2,1,6,8,2,1]):
print(each)
6
8
2
1
itertools.filterfalse
创建一个迭代器,仅保留 iterable 中在 predicate 计算中为 False 的元素,(过滤掉符合条件的元素)
保留对应真值为False的元素
x = itertools.filterfalse(lambda e: e < 5, (1, 5, 3, 6, 9, 4))
print(list(x))
# [5, 6, 9]
'''元素的值减2小于等于0的为True'''
temp = itertools.filterfalse(lambda x: x - 2 <= 0, [1, 2, 0, 3, 1])
print(list(temp))
# [3]
itertools.groupby
按照分组函数的值对元素进行分组
x = itertools.groupby(range(10), lambda x: x < 5 or x > 8)
for condition, numbers in x:
print(condition, list(numbers))
# True [0, 1, 2, 3, 4]
# False [5, 6, 7, 8]
# True [9]
itertools.islice
上文使用过的函数,对迭代器进行切片
x = itertools.islice(range(10), 0, 9, 2)
print(list(x))
# [0, 2, 4, 6, 8]
itertools.starmap
类似map
>>> x = itertools.starmap(str.islower, 'aBCDefGhI')
>>> print(list(x))
[True, False, False, False, True, True, False, True, False]
itertools.takewhile
创建一个迭代器,将 iterable 中的元素当作 function 的参数计算,与 dropwhile() 函数恰恰相反,当结果的布尔值为 True 时,其元素添加到新迭代器中, 直到有元素的计算结果为 False 时,此元素与之后的元素全部抛弃。
x = itertools.takewhile(lambda e: e < 5, range(10))
print(list(x))
[0, 1, 2, 3, 4]
li =[(2, 3), (3, 1), (4, 6), (5, 3), (6, 5), (7, 2)]
list(itertools.starmap(lambda x,y: x+y, li))
[5, 4, 10, 8, 11, 9]
itertools.zip_longest
类似于zip,不过已较长的列表和迭代器的长度为准
>>> x = itertools.zip_longest(range(3), range(5))
>>> y = zip(range(3), range(5))
>>> print(list(x))
[(0, 0), (1, 1), (2, 2), (None, 3), (None, 4)]
>>> print(list(y))
[(0, 0), (1, 1), (2, 2)]
组合生成器
itertools.product
产生多个列表和迭代器的(积)
- 输入两个迭代器,
- 输出是两个迭代器的组合
x = itertools.product('ABC', range(3))
print(list(x))
[('A', 0), ('A', 1), ('A', 2), ('B', 0), ('B', 1), ('B', 2), ('C', 0), ('C', 1), ('C', 2)]
x = itertools.product([2], [1,2])
print(list(x))
# [(2, 1), (2, 2)]
itertools.permutations
产生指定数目的元素的所有排列(顺序有关)
- 生成指定个数的所有元素的排列
- 遇到原列表或者迭代器有重复元素的现象的时候,也会对应的产生重复项,最好去重
x = itertools.permutations(range(4), 3)
print(list(x))
[(0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 3), (0, 3, 1), (0, 3, 2), (1, 0, 2), (1, 0, 3), (1, 2, 0), (1, 2, 3), (1, 3, 0), (1, 3, 2), (2, 0, 1), (2, 0, 3), (2, 1, 0), (2, 1, 3), (2, 3, 0), (2, 3, 1), (3, 0, 1), (3, 0, 2), (3, 1, 0), (3, 1, 2), (3, 2, 0), (3, 2, 1)]
itertools.combinations
列表或生成器中指定数目的元素不重复的所有组合
-
输入是元素不相同的列表或者生成器,也可以是字符串
-
输出是元素的不同组合
-
输入元素不能有重复的元素,否则会返回相同的组合
-
组合是无序的,只考虑元素本身的unique性。
x = itertools.combinations(range(4), 3)
print(list(x))
# [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
itertools.combinations_with_replacement
允许重复元素的组合
- 输入列表或者生成器
- 返回不同的元素组合
- 可以输入重复的元素,返回是不同的组合
x = itertools.combinations_with_replacement('ABC', 2)
print(list(x))
# [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
Note
itertools.zip_longest
类似于zip,不过已较长的列表和迭代器的长度为准
x = itertools.zip_longest(range(3), range(5))
y = zip(range(3), range(5))
print(list(x))
# [(0, 0), (1, 1), (2, 2), (None, 3), (None, 4)]
# print(list(y))
[(0, 0), (1, 1), (2, 2)]