Interleave multiple lists of the same length in Python

后端 未结 9 1447
刺人心
刺人心 2020-11-22 10:11

In Python, is there a good way to interleave two lists of the same length?

Say I\'m given [1,2,3] and [10,20,30]. I\'d like to transform th

相关标签:
9条回答
  • 2020-11-22 10:23

    Alternative:

    >>> l1=[1,2,3]
    >>> l2=[10,20,30]
    >>> [y for x in map(None,l1,l2) for y in x if y is not None]
    [1, 10, 2, 20, 3, 30]
    

    This works because map works on lists in parallel. It works the same under 2.2. By itself, with None as the called functions, map produces a list of tuples:

    >>> map(None,l1,l2,'abcd')
    [(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
    

    Then just flatten the list of tuples.

    The advantage, of course, is map will work for any number of lists and will work even if they are different lengths:

    >>> l1=[1,2,3]
    >>> l2=[10,20,30]
    >>> l3=[101,102,103,104]
    >>> [y for x in map(None,l1,l2,l3) for y in x if y in not None]
    [1, 10, 101, 2, 20, 102, 3, 30, 103, 104]
    
    0 讨论(0)
  • 2020-11-22 10:28

    Given

    a = [1, 2, 3]
    b = [10, 20, 30]
    c = [100, 200, 300, 999]
    

    Code

    Assuming lists of equal length, you can get an interleaved list with itertools.chain and zip:

    import itertools
    
    
    list(itertools.chain(*zip(a, b)))
    # [1, 10, 2, 20, 3, 30]
    

    Alternatives

    itertools.zip_longest

    More generally with unequal lists, use zip_longest (recommended):

    [x for x in itertools.chain(*itertools.zip_longest(a, c)) if x is not None]
    # [1, 100, 2, 200, 3, 300, 999]
    

    Many lists can safely be interleaved:

    [x for x in itertools.chain(*itertools.zip_longest(a, b, c)) if x is not None]
    # [1, 10, 100, 2, 20, 200, 3, 30, 300, 999]
    

    more_itertools+

    A library that ships with the roundrobin itertools recipe, interleave and interleave_longest.

    import more_itertools
    
    
    list(more_itertools.roundrobin(a, b))
    # [1, 10, 2, 20, 3, 30]
    
    list(more_itertools.interleave(a, b))
    # [1, 10, 2, 20, 3, 30]
    
    list(more_itertools.interleave_longest(a, c))
    # [1, 100, 2, 200, 3, 300, 999]
    

    yield from

    Finally, for something interesting in Python 3 (though not recommended):

    list(filter(None, ((yield from x) for x in zip(a, b))))
    # [1, 10, 2, 20, 3, 30]
    
    list([(yield from x) for x in zip(a, b)])
    # [1, 10, 2, 20, 3, 30]
    

    +Install using pip install more_itertools

    0 讨论(0)
  • 2020-11-22 10:30

    Having posted the question, I've realised that I can simply do the following:

    [val for pair in zip(l1, l2) for val in pair]
    

    where l1 and l2 are the two lists.


    If there are N lists to interleave, then

    lists = [l1, l2, ...]
    [val for tup in zip(*lists) for val in tup]
    
    0 讨论(0)
  • 2020-11-22 10:31

    Too late to the party, and there is plenty of good answers but I would also like to provide a simple solution using extend() method:

    list1 = [1, 2, 3]
    list2 = [10, 20, 30]
    
    new_list = []
    for i in range(len(list1)):
        new_list.extend([list1[i], list2[i]])
    print(new_list)
    

    Output:

    [1, 10, 2, 20, 3, 30]
    
    0 讨论(0)
  • 2020-11-22 10:34

    To answer the question's title of "Interleave multiple lists of the same length in Python", we can generalize the 2-list answer of @ekhumoro. This explicitly requires that the lists are the same length, unlike the (elegant) solution by @NPE

    import itertools
    
    def interleave(lists):
        """Interleave a list of lists.
    
        :param lists: List of lists; each inner length must be the same length.
        :returns: interleaved single list
        :rtype: list
    
        """
        if len(set(len(_) for _ in lists)) > 1:
            raise ValueError("Lists are not all the same length!")
        joint = list(itertools.chain(*lists))
        for l_idx, li in enumerate(lists):
            joint[l_idx::len(lists)] = li
        return joint
    

    Examples:

    >>> interleave([[0,2,4], [1, 3, 5]])
    [0, 1, 2, 3, 4, 5]
    >>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12]])
    [0, 1, 10, 2, 3, 11, 4, 5, 12]
    >>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14, 15]])
    [0, 1, 10, 13, 2, 3, 11, 14, 4, 5, 12, 15]
    >>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14]])
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 10, in interleave
    ValueError: Lists are not all the same length!
    >>> interleave([[0,2,4]])
    [0, 2, 4]
    
    0 讨论(0)
  • For Python>=2.3, there's extended slice syntax:

    >>> a = [0, 2, 4, 6, 8]
    >>> b = [1, 3, 5, 7, 9]
    >>> c = a + b
    >>> c[::2] = a
    >>> c[1::2] = b
    >>> c
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    The line c = a + b is used as a simple way to create a new list of exactly the right length (at this stage, its contents are not important). The next two lines do the actual work of interleaving a and b: the first one assigns the elements of a to all the even-numbered indexes of c; the second one assigns the elements of b to all the odd-numbered indexes of c.

    0 讨论(0)
提交回复
热议问题