在Python中交错两个列表

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

说我给[1,2,3][10,20,30] 。 我想把它们转换成[1,10,2,20,3,30]

发布这个问题后,我意识到我可以简单地做以下事情:

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

其中l1l2是两个列表。

对于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] 

c = a + b被用作一个简单的方法来创build一个正确长度的新列表(在这个阶段,其内容并不重要)。 接下来的两行做交织ab的实际工作:第一个将a的元素赋值给c所有偶数索引; 第二个将b的元素分配给b的所有奇数索引。

替代scheme:

 >>> 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] 

这是因为地图在列表上并行工作。 它在2.2下工作相同 。 本身, None作为被调用的函数, map产生一个元组列表:

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

然后只是压扁元组列表。

当然,好处是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] 

我需要一个方法来做到这一点与接受的答案不解决的不同大小的列表。

我的解决scheme使用一个发电机,它的使用看起来好一点,因为它:

 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() 

和它的用法:

 >>> 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'] 

有几个选项。

 # Given a = [1, 2, 3] b = [10, 20, 30] 

你可以用itertools得到一个交错列表:

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

考虑安装more_itertools – 一个实现了interleaveinterleave_longestroundrobin itertools配方的库 。

 import more_itertools list(more_itertools.interleave(a, b)) # [1, 10, 2, 20, 3, 30] list(more_itertools.roundrobin(a, b)) # [1, 10, 2, 20, 3, 30] 

最后,有趣的是,在Python 3中:

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

我最喜欢aix的解决scheme。 这里是我认为应该在2.2中工作的另一种方式:

 >>> x=range(3) >>> x [0, 1, 2] >>> y=range(7,10) >>> y [7, 8, 9] >>> sum(zip(x,y),[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "tuple") to list >>> sum(map(list,zip(x,y)),[]) [0, 7, 1, 8, 2, 9] 

还有一个方法:

 >>> a=[x,y] >>> [a[i][j] for j in range(3) for i in (0,1)] [0, 7, 1, 8, 2, 9] 

和:

 >>> sum((list(i) for i in zip(x,y)),[]) [0, 7, 1, 8, 2, 9] 
 [el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None] 

只要你None你想要保留的无