在Python中优雅快速地连续遍历两个或多个容器的方法?
我有三个集合(collection.deques),我需要做的是遍历这三个集合,并对每个集合执行相同的操作:
for obj in deque1:
some_action(obj)
for obj in deque2:
some_action(obj)
for obj in deque3:
some_action(obj)
我在寻找一个函数XXX,理想情况下我希望能这样写:
for obj in XXX(deque1, deque2, deque3):
some_action(obj)
这里重要的是,XXX必须足够高效——不能复制数据或者默默地使用range()等。我原本希望能在内置函数中找到这样的东西,但到目前为止我没有找到类似的。
在Python中已经有这样的东西吗,还是我需要自己写一个函数呢?
10 个回答
9
你可能觉得我有点疯狂,但为什么大家觉得用itertools是必须的呢?这样做有什么问题呢:
def perform_func_on_each_object_in_each_of_multiple_containers(func, containers):
for container in containers:
for obj in container:
func(obj)
perform_func_on_each_object_in_each_of_multiple_containers(some_action, (deque1, deque2, deque3)
更疯狂的是:你可能只会用一次这个功能。为什么不直接这样做呢:
for d in (deque1, deque2, deque3):
for obj in d:
some_action(obj)
这样做的意思一目了然,不用去查长长的函数名或者itertools里某个东西的文档。
21
答案在itertools这个库里。
itertools.chain(*iterables)
这个功能可以创建一个迭代器,它会从第一个可迭代对象中返回元素,直到这个对象里的元素用完为止。然后,它会继续到下一个可迭代对象,直到所有的可迭代对象都用完。这个功能可以用来把连续的序列当作一个整体来处理。相当于:
def chain(*iterables): # chain('ABC', 'DEF') --> A B C D E F for it in iterables: for element in it: yield element
55
根据你想要处理这些项目的顺序:
import itertools
for items in itertools.izip(deque1, deque2, deque3):
for item in items:
some_action(item)
for item in itertools.chain(deque1, deque2, deque3):
some_action(item)
我建议这样做,以避免死写实际的双端队列或双端队列的数量:
deques = [deque1, deque2, deque3]
for item in itertools.chain(*deques):
some_action(item)
为了演示上面方法顺序的不同:
>>> a = range(5)
>>> b = range(5)
>>> c = range(5)
>>> d = [a, b, c]
>>>
>>> for items in itertools.izip(*d):
... for item in items:
... print item,
...
0 0 0 1 1 1 2 2 2 3 3 3 4 4 4
>>>
>>> for item in itertools.chain(*d):
... print item,
...
0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
>>>