2011-10-30 39 views
39

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

说我给了[1,2,3][10,20,30]。我想将这些转换为[1,10,2,20,3,30]

+0

你知道那2.2现在十岁了?没有理由继续使用它。 –

+3

@DanielRoseman:我知道。在这种情况下,我别无选择。 – NPE

+0

不推荐,但试试这个:'it = iter(l1);列表((yield of next(it))or i for in in in2)' –

回答

59

已经张贴的问题,我已经意识到我可以简单地做到以下几点:

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

其中l1l2是两个列表。

+2

只有在l1和l2具有相同数量的元素时才有效 – Emmanuel

+1

@Emmanuel:问题是“在Python中,是否有一种很好的方法来交织两个列表**长度相同**?“ – NPE

+2

谢谢我认为我需要新的眼镜。 – Emmanuel

1

我最喜欢aix的解决方案。这里是另一种方式,我认为在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] 
5

备选:

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

该作品因为map并行工作在列表上。它在2.2下面works the same。就其本身而言,与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] 
+1

'也会过滤掉'0',如果'y不是'则不太脆弱。 –

+0

@Jochen Ritzel:谢谢!我赞同你。固定。我只写了一些肌肉...... –

29

用于Python> = 2.3,有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] 

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

5

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

我的解决方案使用一台发电机及其使用看起来有点更好,因为它:

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

有几种选择。

# 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 recipe实现。

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] 
0
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None] 

只要你没有None要保持