python itertools

islice

切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
>>> def count(n):
... while True:
... yield n
... n += 1
...
>>> c = count(0)
>>> c[10:20]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'generator' object is not subscriptable

>>> # Now using islice()
>>> import itertools
>>> for x in itertools.islice(c, 10, 20):
... print(x)
...
10
11
12
13
14
15
16
17
18
19
>>>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [97]: ls = [0,1,2,3,4,5,6,7,8,9]
In [98]: for i in itertools.islice(ls, None, 3): # 等价于ls[:3]
...: print(i)
0
1
2

In [99]: for i in itertools.islice(ls, 4, None): # 类似于ls[4:]
...: print(i)
4
5
6
7
8
9

dropwhile

抛弃符合函数的值,但是实际测试跟我所理解的有所出入

如下代码本来期望去掉b开头的,结果却全部输出了

1
2
3
4
5
6
7
8
In [105]: for i in itertools.dropwhile(lambda item : item.startswith('b'), ls):
...: print(i)
a1
b1
a2
b2
a3
b3

再试,去掉小于4的
怪哉了,换成数字却又可以了

1
2
3
4
5
6
7
In [106]: ls = [1,2,3,4,5,6,7,8]
In [107]: for i in itertools.dropwhile(lambda item : item < 5, ls):
...: print(i)
5
6
7
8

再试,条件一样还是去掉大于5的,改变列表值
这次又不是我所期望的
但是好像有点眉目了,第一个item不满足条件就直接输出全部了
我们是不是可以假设该函数抛弃前面满足条件的值,直到出现不满足的值后就不再判断,即使在这个值后可能还会出现满足条件的值也不再抛弃

1
2
3
4
5
6
7
8
9
10
11
In [108]: ls = [6,3,8,9,1,5,4,2]
In [109]: for i in itertools.dropwhile(lambda item : item < 5, ls):
...: print(i)
6
3
8
9
1
5
4
2

二话不说,赶紧验证一下

1
2
3
4
5
6
7
8
9
10
11
In [110]: ls = [1,2,3,4,6,3,8,9,1,5,4,2]
In [111]: for i in itertools.dropwhile(lambda item : item < 5, ls):
...: print(i)
6
3
8
9
1
5
4
2

果然如此

permutations

排列(与顺序有关)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
In [112]: items = ['a', 'b', 'c']
In [113]: for i in itertools.permutations(items): # 默认排列的长度为items的长度
...: print(i)
('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a')

In [114]: for i in itertools.permutations(items, 2): # 指定排列的长度
...: print(i)
('a', 'b')
('a', 'c')
('b', 'a')
('b', 'c')
('c', 'a')
('c', 'b')

combinations

组合(与顺序无关)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
In [112]: items = ['a', 'b', 'c']

In [116]: for i in itertools.combinations(items, 3):
...: print(i)
('a', 'b', 'c')

In [117]: for i in itertools.combinations(items, 2):
...: print(i)
('a', 'b')
('a', 'c')
('b', 'c')

In [118]: for i in itertools.combinations(items, 1):
...: print(i)
('a',)
('b',)
('c',)

combinations_with_replacement

元素可重复出现的组合

1
2
3
4
5
6
In [119]: items = ['a', 'b']
In [120]: for i in itertools.combinations_with_replacement(items, 2):
...: print(i)
('a', 'a')
('a', 'b')
('b', 'b')

zip_longest

功能与内置函数zip类似,只是输出以最长的序列为准

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
In [45]: import itertools
In [26]: als = [1,2,3,4,5,6]
In [27]: bls = ['a','b','c','d']

In [46]: for a,b in itertools.zip_longest(als,bls): # 输出以最长的序列为准,不足的为None
...: print(a,b)
1 a
2 b
3 c
4 d
5 None
6 None

# None替换成fillvalue的值
In [48]: for a,b in itertools.zip_longest(als,bls,fillvalue='letter'):
...: print(a,b)
1 a
2 b
3 c
4 d
5 letter
6 letter

chain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
In [49]: import itertools
In [50]: als = [1,2,3,4]
In [51]: bls = ('a','b','c','d')
# 注意两种不同类型的可迭代随想也可以完美输出
In [52]: for item in itertools.chain(als,bls):
...: print(item)
1
2
3
4
a
b
c
d

# 类型
In [53]: type(itertools.chain(als,bls))
Out[53]: itertools.chain