Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An elegant and fast way to consecutively iterate over two or more containers in Python?

I have three collection.deques and what I need to do is to iterate over each of them and perform the same action:

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

I'm looking for some function XXX which would ideally allow me to write:

for obj in XXX(deque1, deque2, deque3):       some_action(obj) 

The important thing here is that XXX have to be efficient enough - without making copy or silently using range(), etc. I was expecting to find it in built-in functions, but I found nothing similar to it so far.

Is there such thing already in Python or I have to write a function for that by myself?

like image 335
lithuak Avatar asked Jan 25 '11 16:01

lithuak


People also ask

What is iterate over in Python?

Many things in Python are iterables, but not all of them are sequences. An iterator is an object representing a stream of data. It does the iterating over an iterable. You can use an iterator to get the next value or to loop over it.

How do I use two iterators in Python?

Use the izip() Function to Iterate Over Two Lists in Python It then zips or maps the elements of both lists together and returns an iterator object. It returns the elements of both lists mapped together according to their index.

Which function returns an iterable with a next () method that yields the next element in a sequence?

Specifically, an iterator is any object which implements the Iterator protocol by having a next() method that returns an object with two properties: value. The next value in the iteration sequence.


2 Answers

Depending on what order you want to process the items:

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) 

I'd recommend doing this to avoid hard-coding the actual deques or number of deques:

deques = [deque1, deque2, deque3] for item in itertools.chain(*deques):     some_action(item) 

To demonstrate the difference in order of the above methods:

>>> 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 >>> 
like image 114
FogleBird Avatar answered Oct 15 '22 17:10

FogleBird


The answer is in itertools

itertools.chain(*iterables) 

Make an iterator that returns elements from the first iterable until it is exhausted, then proceeds to the next iterable, until all of the iterables are exhausted. Used for treating consecutive sequences as a single sequence. Equivalent to:

def chain(*iterables):     # chain('ABC', 'DEF') --> A B C D E F     for it in iterables:         for element in it:             yield element 
like image 32
Drakosha Avatar answered Oct 15 '22 16:10

Drakosha