Search code examples
pythonpython-itertools

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.


Solution

  • This one works alright:

    >>> from itertools import chain, islice, izip, cycle
    >>> list(islice(cycle(chain.from_iterable(izip(server1, server2, server3))), 0, 18))
    ['a', 'd', 'g', 'b', 'e', 'h', 'c', 'f', 'i', 'a', 'd', 'g', 'b', 'e', 'h', 'c', 'f', 'i']
    

    Note, the list and islice are just for demonstration purposes to give something to display and prevent infinite output...

    Now, it gets more interesting if you have unequal length lists. Then izip_longest will be your friend, but it might be worth a function at this point:

    import itertools
    def cycle_through_servers(*server_lists):
        zipped = itertools.izip_longest(*server_lists, fillvalue=None)
        chained = itertools.chain.from_iterable(zipped)
        return itertools.cycle(s for s in chained if s is not None)
    

    demo:

    >>> from itertools import islice
    >>> server3 = ['g', 'h', 'i', 'j']
    >>> list(islice(cycle_through_servers(server1, server2, server3), 0, 20))
    ['a', 'd', 'g', 'b', 'e', 'h', 'c', 'f', 'i', 'j', 'a', 'd', 'g', 'b', 'e', 'h', 'c', 'f', 'i', 'j']