python itertools模块小结

itertools 包含的所有方法

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
count([n]) --> n, n+1, n+2, ...
cycle(p) --> p0, p1, ... plast, p0, p1, ...
repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times
Iterators terminating on the shortest input sequence:
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...
compress(data, selectors) --> (d[0] if s[0]), (d[1] if s[1]), ...
dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails
groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)
ifilter(pred, seq) --> elements of seq where pred(elem) is True
ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False
islice(seq, [start,] stop [, step]) --> elements from
seq[start:stop:step]
imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...
tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n
takewhile(pred, seq) --> seq[0], seq[1], until pred fails
izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ...
izip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ...
Combinatoric generators:
product(p, q, ... [repeat=1]) --> cartesian product
permutations(p[, r])
combinations(p, r)
combinations_with_replacement(p, r)

第一部分

itertools.count

创建一个迭代器,生成从n开始的连续整数,如果忽略n,则从0开始计算(注意:此迭代器不支持长整数)
如果超出了sys.maxint,计数器将溢出并继续从-sys.maxint-1开始计算。

定义

1
2
3
4
5
def count(firstval=0, step=1):
x = firstval
while 1:
yield x
x += step

使用

1
2
3
4
5
6
In [12]: for i in itertools.izip(count(1), ['a', 'b', 'c']):
....: print(i)
....:
(1, 'a')
(2, 'b')
(3, 'c')

itertools.cycle

创建一个迭代器,对iterable中的元素反复执行循环操作,内部会生成iterable中的元素的一个副本,此副本用于返回循环中的重复项.
定义

1
2
3
4
5
6
7
8
9
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
saved = []
for element in iterable:
yield element
saved.append(element)
while saved:
for element in saved:
yield element

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [10]: for item in itertools.cycle(['a','b', 'c']):
....: i += 1
....: if i == 10:
....: break
....: print(i, item)
....:
(1, 'a')
(2, 'b')
(3, 'c')
(4, 'a')
(5, 'b')
(6, 'c')
(7, 'a')
(8, 'b')
(9, 'c')


itertools.repeat

创建一个迭代器,重复生成object,times(如果已提供)指定重复计数,如果未提供times,将无止尽返回该对象。

定义

1
2
3
4
5
6
7
8
def repeat(object, times=None):
# repeat(10, 3) --> 10 10 10
if times is None:
while True:
yield object
else:
for i in xrange(times):
yield object

使用

1
2
3
4
5
6
7
8
In [14]: for i in itertools.repeat('over-and-over', 5):
....: print(i)
....:
over-and-over
over-and-over
over-and-over
over-and-over
over-and-over

第二部分

itertools.chain

将多个迭代器作为参数, 但只返回单个迭代器, 它产生所有参数迭代器的内容, 就好像他们是来自于一个单一的序列.

定义

1
2
3
4
5
def chain(*iterables):
# chain('ABC', 'DEF') --> A B C D E F
for it in iterables:
for element in it:
yield element

使用

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
In [16]: for i in itertools.chain([1,2], ['a', 'b', 'c']):
....: print(i)
....:
1
2
a
b
c
In [19]: def listdir(func, items):
....: return itertools.chain.from_iterable(itertools.imap(func, items))
In [20]: list(listdir(os.listdir, '.'))
Out[20]:
['.bash_logout',
'.bash_profile',
'.bashrc',
'.cshrc',
'.tcshrc',
'.bash_history',
'.pki',
....
'.my.cnf',
'_temp']

itertools.compress

提供一个选择列表,对原始数据进行筛选

定义

1
2
3
def compress(data, selectors):
# compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
return (d for d, s in izip(data, selectors) if s)

使用

1
2
In [23]: list(itertools.compress('ABCDEFG', [1,0,0,1,1,1]))
Out[23]: ['A', 'D', 'E', 'F']


itertools.dropwhile(predicate, iterable)

创建一个迭代器,只要函数predicate(item)为True,就丢弃iterable中的项,如果predicate返回False,就会生成iterable中的项和所有后续项。

即:在条件为false之后的第一次, 返回迭代器中剩下来的项(包括当前项).

定义

1
2
3
4
5
6
7
8
9
def dropwhile(predicate, iterable):
# dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
yield x
break
for x in iterable:
yield x

使用

1
2
In [30]: list(itertools.dropwhile(lambda x: x<1, [-1,0,1,2,3,4,1,-2]))
Out[30]: [1, 2, 3, 4, 1, -2]


itertools.groupby(iterable[, keyfunc])

返回一个产生按照key进行分组后的值集合的迭代器.

如果iterable在多次连续迭代中生成了同一项,则会定义一个组,如果将此函数应用一个分类列表,那么分组将定义该列表中的所有唯一项,key(如果已提供)是一个函数,应用于每一项,如果此函数存在返回值,该值将用于后续项而不是该项本身进行比较,此函数返回的迭代器生成元素(key, group),其中key是分组的键值,group是迭代器,生成组成该组的所有项。

即:按照keyfunc函数对序列每个元素执行后的结果分组(每个分组是一个迭代器), 返回这些分组的迭代器

注意: 分组之前 iterable 需要是一个排序序列

1
2
3
4
5
6
7
8
9
10
11
12
In [38]: qs = [{'age': 10, 'name': 'yangcan'},
{'age': 12, 'name': 'xiaoyang'},
{'age': 10, 'name': 'xx'},
{'age': 13, 'name': 'lisi'}]
In [40]: for name, group in itertools.groupby(sorted(qs), lambda x: x['age']):
print(name, list(group))
....:
(10, [{'age': 10, 'name': 'xx'}, {'age': 10, 'name': 'yangcan'}])
(12, [{'age': 12, 'name': 'xiaoyang'}])
(13, [{'age': 13, 'name': 'lisi'}])

使用operator.itemgetter

1
2
3
4
5
6
7
In [43]: from operator import itemgetter
In [44]: for name, group in itertools.groupby(sorted(qs), itemgetter('age')):
print(name, list(group))
....:
(10, [{'age': 10, 'name': 'xx'}, {'age': 10, 'name': 'yangcan'}])
(12, [{'age': 12, 'name': 'xiaoyang'}])
(13, [{'age': 13, 'name': 'lisi'}])

TODO 未完待续 …

分享即快乐,谢谢你请思哲小朋友吃糖!