2012-11-05 59 views
4

我想寫一個Python函數,它將兩個列表作爲參數並將它們交錯。組件列表的順序應該保留。如果列表的長度不相同,則較長列表的元素應該在結果列表的末尾 處結束。 例如,我希望把這個殼牌:在python v。2中插入兩個不同長度的列表?

interleave(["a", "b"], [1, 2, 3, 4]) 

而且把它恢復:

["a", 1, "b", 2, 3, 4] 

如果你能幫助我,我將不勝感激。

回答

1

下面是我該怎麼做,使用itertools模塊的各個位。它適用於任何數量的iterables的,而不是兩個:

from itertools import chain, izip_longest # or zip_longest in Python 3 
def interleave(*iterables): 

    sentinel = object() 
    z = izip_longest(*iterables, fillvalue = sentinel) 
    c = chain.from_iterable(z) 
    f = filter(lambda x: x is not sentinel, c) 

    return list(f) 
1

你可以試試這個:

In [30]: from itertools import izip_longest 

In [31]: l = ['a', 'b'] 

In [32]: l2 = [1, 2, 3, 4] 

In [33]: [item for slist in izip_longest(l, l2) for item in slist if item is not None] 
Out[33]: ['a', 1, 'b', 2, 3, 4] 

izip_longest「拉鍊」兩個列表一起,但不是在長度最短停止列表中,它一直持續到最長的一個已耗盡:

In [36]: list(izip_longest(l, l2)) 
Out[36]: [('a', 1), ('b', 2), (None, 3), (None, 4)] 

然後,您可以通過在每一對在壓縮列表中每個項目迭代,忽略那些有VALU添加項目e的None。正如@Blckknight所指出的那樣,如果您的原始列表已經有None的值,這將無法正常運行。如果在您的情況下可以這樣做,您可以使用izip_longestfillvalue屬性來填充None以外的內容(正如@Blckknight在他的回答中所做的那樣)。

這裏是上面的例子作爲一個函數:

In [37]: def interleave(*iterables): 
    ....:  return [item for slist in izip_longest(*iterables) for item in slist if item is not None] 
    ....: 

In [38]: interleave(l, l2) 
Out[38]: ['a', 1, 'b', 2, 3, 4] 

In [39]: interleave(l, l2, [44, 56, 77]) 
Out[39]: ['a', 1, 44, 'b', 2, 56, 3, 77, 4] 
+0

您的版本不會與包含'None'作爲值的列表一起使用。這就是爲什麼我在我的版本中創建了一個獨特的哨兵對象,所以它不會絆倒列表中已有的任何奇怪的值。 – Blckknght

+0

@Blckknght陷阱 - 你的版本不錯,我同意:)我會編輯答案提及。 – RocketDonkey

0

一個不很完美的解決方案,但仍可能會有所幫助

def interleave(lista, listb): 
    (tempa, tempb) = ([i for i in reversed(lista)], [i for i in reversed(listb)]) 
    result = [] 
    while tempa or tempb: 
     if tempa: 
      result.append(tempa.pop()) 
     if tempb: 
      result.append(tempb.pop()) 

    return result 

或在單行

def interleave2(lista, listb): 
    return reduce(lambda x,y : x + y, 
        map(lambda x: x[0] + x[1], 
         [(lista[i:i+1], listb[i:i+1]) 
         for i in xrange(max(len(lista),len(listb)))])) 
0

另一種解決方案是基於:我該怎麼做?那麼,幾乎用手,使用內置在zip(),和延伸通過的較長一個的尾部壓縮和解中較短的列表的長度的結果:

#!python2 

def interleave(lst1, lst2): 
    minlen = min(len(lst1), len(lst2))  # find the length of the shorter 
    tail = lst1[minlen:] + lst2[minlen:]  # get the tail 
    result = [] 
    for t in zip(lst1, lst2):     # use a standard zip 
     result.extend(t)      # expand tuple to two items 
    return result + tail      # result of zip() plus the tail 

print interleave(["a", "b"], [1, 2, 3, 4]) 
print interleave([1, 2, 3, 4], ["a", "b"]) 
print interleave(["a", None, "b"], [1, 2, 3, None, 4]) 

它打印結果:

['a', 1, 'b', 2, 3, 4] 
[1, 'a', 2, 'b', 3, 4] 
['a', 1, None, 2, 'b', 3, None, 4] 
相關問題