2011-10-30 73 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要保持