python-itertools

发布时间 2023-06-07 09:58:15作者: 贝壳里的星海

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)]