Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cycle through multiple list using itertools.cycle()

I have a list of servers. Every server has a list of name on it. example:

server1 = ['a','b','c']
server2 = ['d','e','f']
server3 = ['g','h','i']

I want to iterate per server name not per server. For example after picking 'a' in server1, move to 'd' (not 'b') and so on. If I'm going to use itertools.cycle(), do I have to create a list of server to cycle through? My expected result is ['a','d','g','b','e','h','c','f','i']. Can you give me a simple example on how to cycle in multiple list.

like image 977
unice Avatar asked Mar 24 '15 06:03

unice


People also ask

What does cycle () do in Python?

The cycle() function accepts an iterable and generates an iterator, which contains all of the iterable's elements. In addition to these elements, it contains a copy of each element.

Is Itertools faster than for loops?

That being said, the iterators from itertools are often significantly faster than regular iteration from a standard Python for loop.


2 Answers

We can also use itertools.chain.from_iterable() which is faster in comparison.

import itertools

server1 = ['a','b','c']
server2 = ['d','e','f']
server3 = ['g','h','i']

print list(itertools.chain.from_iterable(zip(server1,server2,server3)))

Results:

['a', 'd', 'g', 'b', 'e', 'h', 'c', 'f', 'i']
like image 171
Tanveer Alam Avatar answered Nov 06 '22 03:11

Tanveer Alam


You can do it the with zip and reduce built-in functions (and in python3 functools.reduce):

>>> list_of_servers=[server1,server2,server3]
>>> s=reduce(lambda x,y:x+y,zip(*list_of_servers))
>>> s
('a', 'd', 'g', 'b', 'e', 'h', 'c', 'f', 'i')

Or instead of reduce() for long lists you can use itertools.chain to concatenate the sub-lists that return a generator:

>>> list(chain(*zip(*[server1,server2,server3])))
['a', 'd', 'g', 'b', 'e', 'h', 'c', 'f', 'i']

NOTE that if you want to iterate over your result you don't have to use list on the result of chain. You can just do something like:

for element in chain(*zip(*[server1,server2,server3])):
     #do stuff

Benchmarking on the preceding recipes:

#reduce()
:~$ python -m timeit "server1 = ['a','b','c'];server2 = ['d','e','f'];server3 = ['g','h','i'];reduce(lambda x,y:x+y,zip(*[server1,server2,server3]))"
1000000 loops, best of 3: 1.11 usec per loop
#itertools.chain()
:~$ python -m timeit "server1 = ['a','b','c'];server2 = ['d','e','f'];server3 = ['g','h','i'];from itertools import chain;chain(*zip(*[server1,server2,server3]))"
100000 loops, best of 3: 2.02 usec per loop

Note that if you don't put the servers within a list it would be faster :

:~$ python -m timeit "server1 = ['a','b','c'];server2 = ['d','e','f'];server3 = ['g','h','i'];reduce(lambda x,y:x+y,zip(server1,server2,server3))"
1000000 loops, best of 3: 0.98 usec per loop
like image 29
Mazdak Avatar answered Nov 06 '22 02:11

Mazdak