我想寫一個Python函數,它將兩個列表作爲參數並將它們交錯。組件列表的順序應該保留。如果列表的長度不相同,則較長列表的元素應該在結果列表的末尾 處結束。 例如,我希望把這個殼牌:在python v。2中插入兩個不同長度的列表?
interleave(["a", "b"], [1, 2, 3, 4])
而且把它恢復:
["a", 1, "b", 2, 3, 4]
如果你能幫助我,我將不勝感激。
我想寫一個Python函數,它將兩個列表作爲參數並將它們交錯。組件列表的順序應該保留。如果列表的長度不相同,則較長列表的元素應該在結果列表的末尾 處結束。 例如,我希望把這個殼牌:在python v。2中插入兩個不同長度的列表?
interleave(["a", "b"], [1, 2, 3, 4])
而且把它恢復:
["a", 1, "b", 2, 3, 4]
如果你能幫助我,我將不勝感激。
下面是我該怎麼做,使用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)
你可以試試這個:
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_longest
的fillvalue
屬性來填充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]
一個不很完美的解決方案,但仍可能會有所幫助
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)))]))
另一種解決方案是基於:我該怎麼做?那麼,幾乎用手,使用內置在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]
您的版本不會與包含'None'作爲值的列表一起使用。這就是爲什麼我在我的版本中創建了一個獨特的哨兵對象,所以它不會絆倒列表中已有的任何奇怪的值。 – Blckknght
@Blckknght陷阱 - 你的版本不錯,我同意:)我會編輯答案提及。 – RocketDonkey