Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to elegantly interleave two lists of uneven length in python?

I want to merge two lists in python, with the lists being of different lengths, so that the elements of the shorter list are as equally spaced within the final list as possible. i.e. I want to take [1, 2, 3, 4] and ['a','b'] and merge them to get a list similar to [1, 'a', 2, 3, 'b', 4]. It needs to be able to function with lists that aren't exact multiples too, so it could take [1, 2, 3, 4, 5] and ['a', 'b', 'c'] and produce [1, 'a', 2, 'b', 3, 'c', 4, 5] or similar. It needs to preserve the ordering of both lists.

I can see how to do this by a long-winded brute force method but since Python seems to have a vast array of excellent tools to do all sorts of clever things which I don't know about (yet) I wondered whether there's anything more elegant I can use?

NB: I'm using Python 3.3.

like image 538
Jack Aidley Avatar asked Oct 10 '13 10:10

Jack Aidley


People also ask

How do you interleave three lists in Python?

To interleave multiple lists of the same length in Python, we can use list comprehension and zip . We have 3 lists l1 , l2 , and l3 . And then we put them into the lists list. Then to interleave all the lists, we call zip with all the lists in lists as arguments.

How do you make two lists identical in Python?

Method 3 : Using sum() + zip() + len() Using sum() + zip() , we can get sum of one of the list as summation of 1 if both the index in two lists have equal elements, and then compare that number with size of other list.


1 Answers

Borrowing heavily from Jon Clements' solution, you could write a function that takes an arbitrary number of sequences and returns merged sequence of evenly-spaced items:

import itertools as IT

def evenly_spaced(*iterables):
    """
    >>> evenly_spaced(range(10), list('abc'))
    [0, 1, 'a', 2, 3, 4, 'b', 5, 6, 7, 'c', 8, 9]
    """
    return [item[1] for item in
            sorted(IT.chain.from_iterable(
            zip(IT.count(start=1.0 / (len(seq) + 1), 
                         step=1.0 / (len(seq) + 1)), seq)
            for seq in iterables))]

iterables = [
    ['X']*2,
    range(1, 11),
    ['a']*3
    ]

print(evenly_spaced(*iterables))

yields

[1, 2, 'a', 3, 'X', 4, 5, 'a', 6, 7, 'X', 8, 'a', 9, 10]
like image 115
unutbu Avatar answered Oct 16 '22 16:10

unutbu