在Python中交错多个相同长度的列表

NPE*_*NPE 72 python list

在Python中,是否有一种交错两个相同长度列表的好方法?

说我给[1,2,3][10,20,30].我想把它们变成[1,10,2,20,3,30].

NPE*_*NPE 98

发布问题后,我意识到我可以简单地执行以下操作:

[val for pair in zip(l1, l2) for val in pair]
Run Code Online (Sandbox Code Playgroud)

两个列表的位置l1l2位置.


如果有N个列表要交错,那么

lists = [l1, l2, ...]
[val for tup in zip(*lists) for val in tup]
Run Code Online (Sandbox Code Playgroud)

有关更多配方,请按照最佳方式将列表与其后缀值交错.所展示的一些方法可以推广到两个或更多个相等长度的列表.

  • @Emmanuel:问题是"在Python中,是否有一种很好的方法可以交错两个相同长度**的列表**?" (8认同)
  • 仅当l1和l2具有相同数量的元素时才有效 (5认同)
  • 谢谢,我想我需要一副新眼镜. (5认同)
  • 如果您想填充到最长列表,请对 python2 使用 `izip_longest`,对 python3 使用 `zip_longest` `[val forpair in itertools.zip_longest(l1, l2) for val inpair]` 结果为 `['a '、'b'、'a'、'b'、'a'、'b'、无、'b'、无、'b'、无、'b']` (3认同)

ekh*_*oro 57

对于python> = 2.3,有扩展的切片语法:

>>> 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]
Run Code Online (Sandbox Code Playgroud)

该行c = a + b用作创建恰当长度的新列表的简单方法(在此阶段,其内容并不重要).接下来的两行交错的实际工作ab:第一个指定的元素a全部偶数的指标c; 第二个将b所有奇数索引的元素分配给c.


pyl*_*ang 15

特定

a = [1, 2, 3]
b = [10, 20, 30]
c = [100, 200, 300, 999]
Run Code Online (Sandbox Code Playgroud)

假设长度相等的列表,您可以使用itertools.chain和获得交错列表zip:

import itertools


list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
Run Code Online (Sandbox Code Playgroud)

备择方案

itertools.zip_longest

更一般地说,使用不相等的列表,使用zip_longest(推荐):

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

许多列表可以安全地交错:

[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]
Run Code Online (Sandbox Code Playgroud)

more_itertools+

roundrobinitertools配方一起提供的库,interleave以及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]
Run Code Online (Sandbox Code Playgroud)

yield from

最后,对于Python 3中有趣的东西(虽然不推荐):

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]
Run Code Online (Sandbox Code Playgroud)

+使用安装pip install more_itertools


the*_*olf 7

替代方案:

>>> 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]
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为map并行地在列表工作.它的工作原理与 2.2 相同.就其本身而言,None作为被调用的函数,map生成一个元组列表:

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

然后简化元组列表.

当然,优点是map 适用于任意数量的列表,即使长度不同也可以使用:

>>> 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]
Run Code Online (Sandbox Code Playgroud)


San*_*man 7

我需要一种方法来执行此操作与不同大小的列表,接受的答案没有解决.

我的解决方案使用了一个生成器,它的用法看起来更好一点,因为它:

def interleave(l1, l2):
    iter1 = iter(l1)
    iter2 = iter(l2)
    while True:
        try:
            if iter1 != None:
                yield next(iter1)
        except StopIteration:
            iter1 = None
        try:
            if iter2 != None:
                yield next(iter2)
        except StopIteration:
            iter2 = None
        if iter1 == None and iter2 == None:
            raise StopIteration()
Run Code Online (Sandbox Code Playgroud)

它的用法:

>>> a = [1, 2, 3, 4, 5]
>>> b = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list(interleave(a, b))
[1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', 'f', 'g']
>>> list(interleave(b, a))
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 'g']
Run Code Online (Sandbox Code Playgroud)