在Python中连续迭代两个或更多容器的优雅而快速的方法?

时间:2011-01-25 16:03:14

标签: python iterator

我有三个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 个答案:

答案 0 :(得分:33)

取决于您要处理商品的顺序:

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或deques数量:

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

答案 1 :(得分:13)

答案在itertools

itertools.chain(*iterables)
     

创建一个迭代器,返回第一个iterable中的元素,直到   它已经筋疲力尽,然后继续前进   下一个可迭代,直到所有的   迭代用尽了。用于   将连续序列视为一个   单一序列。相当于:

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

答案 2 :(得分:5)

使用itertools.chain(deque1, deque2, deque3)

答案 3 :(得分:5)

叫我疯了,但为什么使用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.something()

的文档时,显而易见的是显而易见的

答案 4 :(得分:2)

拉链怎么样?

for obj in zip(deque1, deque2, deque3):
    for sub_obj in obj:
        some_action(sub_obj)

答案 5 :(得分:2)

如果我正确理解了您的问题,那么您可以使用map将第一个参数设置为None,将所有其他参数作为列表进行迭代。

E.g(来自iPython提示,但你明白了):

In [85]: p = [1,2,3,4]

In [86]: q = ['a','b','c','d']

In [87]: f = ['Hi', 'there', 'world', '.']

In [88]: for i,j,k in map(None, p,q,f):
   ....:     print i,j,k
   ....:
   ....:
1 a Hi
2 b there
3 c world
4 d .

答案 6 :(得分:2)

我会这样做:

for obj in deque1 + deque2 + deque3:  
some_action(obj)  

答案 7 :(得分:1)

看起来你想要我tertools.chain

“创建一个迭代器,它返回第一个迭代中的元素,直到它耗尽,然后进入下一个迭代,直到所有的迭代都用尽。用于将连续序列作为单个序列处理。”

答案 8 :(得分:0)

接受一堆迭代,并按顺序为每个迭代生成内容。

def XXX(*lists):
   for aList in lists:
      for item in aList:
         yield item



l1 = [1, 2, 3, 4]
l2 = ['a', 'b', 'c']
l3 = [1.0, 1.1, 1.2]

for item in XXX(l1, l2, l3):
   print item

1
2
3
4
a
b
c
1.0
1.1
1.2

答案 9 :(得分:-1)

Access-Control-Request-Method