一、多个序列迭代
有时候我们希望能够同时遍历多个序列,比如有序列a = [1, 2, 3, 4, 5], b = ['a', 'b', 'c', 'd', 'e'],我们如果要同时遍历的话,可以采用如下的方式:
- >>> xpts = [1, 5, 4, 2, 10, 7]
- >>> ypts = [101, 78, 37, 15, 62, 99]
- >>> for x, y in zip(xpts, ypts):
- ... print(x, y)
- ...
- 1 101
- 5 78
- 4 37
- 2 15
- 10 62
- 7 99
- >>> a = [1, 2, 3, 4]
- >>> b = ['a', 'b', 'c']
- >>> for x, y in zip(a, b):
- ... print(x, y)
- ...
- 1 a
- 2 b
- 3 c
- >>> from itertools import zip_longest
- >>> for i in zip_longest(a, b):
- ... print(i)
- ...
- (1, 'a')
- (2, 'b')
- (3, 'c')
- (4, None)
将几个序列串在一起
我们可以直接看如下的代码:
- >>> from itertools import chain
- >>> a = [1, 2, 3, 4]
- >>> b = ['a', 'b', 'c']
- >>> for x in chain(a, b):
- ... print(x)
- ...
- 1
- 2
- 3
- 4
- a
- b
- c
将嵌套的序列变平
这是一个有意思的问题,因为一般来说当我们需要访问一个数组的时候,比如说a = [1, 2, [3, 4, [5, 6], 7, 8], 9, 10],我们希望能够将他们所有的元素都输出,并使得他们看起来像就是一个一维数组那样,如a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]。我们默认的思路该怎么办呢?只怕一开始就是碰到一个元素的时候会判断它是否为数组,如果是的则递归的去输出它的元素。
Python里面有一个很强大的特性可以很好的实现这个方法:
- from collections import Iterable
- def flatten(items, ignore_types=(str, bytes)):
- for x in items:
- if isinstance(x, Iterable) and not isinstance(x, ignore_types):
- yield from flatten(x)
- else:
- yield x
按照这个方式,我们使用它们的代码如下:
- >>> from nested import flatten
- >>> items = [1, 2, [3, 4, [5, 6], 7], 8]
- >>> for x in flatten(items):
- ... print(x)
- ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
迭代多个有序排列数组
这个问题不太好用一句话描述,就是说假定我们有若干个已经排序的数组了。当我们希望能够去遍历这所有的序列,但是保证我们每次都取出他们中间最小的元素,保证所有输出还是一个严格排序的结果,我们该怎么办呢?实际上,这是一个多路归并排序的问题。在前面的一些文章里有过讨论,不过要做一个好的java实现我们可是费了一番功夫。这里有什么好的招呢?
- >>> import heapq
- >>> a = [1, 4, 7, 10]
- >>> b = [2, 5, 6, 11]
- >>> for c in heapq.merge(a, b):
- ... print(c)
- ...
- 1
- 2
- 4
- 5
- 6
- 7
- 10
- 11
这里是归并两路的数据结果。在一些我们如果要归并多个文件的情况下,也可以这样来做。因为这里heapq.merge不是一次将所有的数据都装载到内存里,它只是每次取很小的一部分,像generator一样。所以对于大文件的合并用这种方式来做。呵呵,寥寥几行代码就解决了问题,不能不说,很好很强大啊。
总结
Iterator的定义方法虽然看起来很简单,但是它的使用也可以非常的复杂和灵活。通过结合一些库的支持,我们可以实现非常强大的计算效果。当然,前提是我们需要知道去哪里找到这些库和知道这些用法。