Skip to content Skip to sidebar Skip to footer

How To Interleave Two Lists Of Different Length?

I'm quite new to Python and I am still having a hard time actually using the language itself into my program. Here's what I have so far: # Purpose: 'twolists' = takes 2 lists, &

Solution 1:

This composes a list comprehension using zip_longest from itertools (which is part of the standard library) to interleave items from both lists into a tuple, which by default uses None as the fillvalue.

This also uses chain also from itertools to flatten the list.

Finally it filters the None items from the list:

from itertools import chain, zip_longest
deftwolists(l1, l2):
    return [x for x in chain(*zip_longest(l1, l2)) if x isnotNone]

Or as recommended from @EliKorvigo, use itertools.chain.from_iterable for iterating lazily:

deftwolists(l1, l2):
    return [x for x in chain.from_iterable(zip_longest(l1, l2)) if x isnotNone]
Testing
In[56]: twolists([0, 1], ['w', 'x'])
Out[56]: [0, 'w', 1, 'x']In[57]: twolists([0, 1], ['w', 'x', 'y', 'z'])
Out[57]: [0, 'w', 1, 'x', 'y', 'z']In[74]: twolists([0, 1, 2, 3], ['w', 'x'])
Out[74]: [0, 'w', 1, 'x', 2, 3]

Solution 2:

deftwolists(list1, list2):
    newlist = []
    a1 = len(list1)
    a2 = len(list2)

    for i inrange(max(a1, a2)):
        if i < a1:
            newlist.append(list1[i])
        if i < a2:
            newlist.append(list2[i])

    return newlist

Solution 3:

A basic approach:

You could zip() the lists normally, and append the rest of the biggest list if both lists are not the same size:

deftwo_lists(lst1, lst2):
    result = []

    for pair inzip(lst1, lst2):
        result.extend(pair)

    iflen(lst1) != len(lst2):
        lsts = [lst1, lst2]
        smallest = min(lsts, key = len)
        biggest = max(lsts, key = len)
        rest = biggest[len(smallest):]
        result.extend(rest)

    return result

Which works as follows:

>>> print(two_lists([], ['w', 'x', 'y', 'z']))
['w', 'x', 'y', 'z']
>>> print(two_lists([0, 1], ['w', 'x']))
[0, 'w', 1, 'x']
>>> print(two_lists([0, 1], ['w', 'x', 'y', 'z']))
[0, 'w', 1, 'x', 'y', 'z']
>>> print(two_lists([0, 1, 2, 3], ['w', 'x']))
[0, 'w', 1, 'x', 2, 3]

Another possible approach:

You could also use collections.deque to convert the lists to deque() objects beforehand, and pop off the beginning of each one with popleft(), until one of the objects is empty. Then you could append the rest of the list that is not yet empty.

Here is an example:

deftwo_lists2(lst1, lst2):
    result = []

    fst, snd = deque(lst1), deque(lst2)

    while fst and snd:
        result.append(fst.popleft())
        result.append(snd.popleft())

    rest = leftover(fst, snd)
    if rest:
        result.extend(rest)

    return result

defleftover(x, y):
    if x andnot y:
        return x

    elif y andnot x:
        return y

    returnNone

Note: Both of the approaches are O(n) time, which is expected for this kind of problem.

Solution 4:

defCombineLists(lst1, lst2):
   return [item for x inzip(lst1,lst2) for item in x] + /
         (lst2[len(lst1):] iflen(lst2)>len(lst1) else lst1[len(lst2):])

Solution 5:

Here's a solution that deals in iterators. The advantage to this is that it will work with any iterable data structure, not just lists.

deftwolists(list1, list2):
    result = []
    iter1 = iter(list1)
    iter2 = iter(list2)
    try:
        whileTrue:
            result.append(next(iter1))
            result.append(next(iter2))
    except StopIteration:
        # This exception will be raised when either of the iterators# hits the end of the sequence.pass# One of the lists is exhausted, but not both of them. We need# to finish exhausting the lists.try:
        whileTrue:
            result.append(next(iter1))
    except StopIteration:
        passtry:
        whileTrue:
            result.append(next(iter2))
    except StopIteration:
        passreturn result

Post a Comment for "How To Interleave Two Lists Of Different Length?"