我正在尝试编写一个Python函数,它以两个列表作为参数,并将它们交错在一起。组件列表的顺序应该被保留。如果列表长度不同,则较长列表的元素应该出现在结果列表的末尾。 例如,我想把这个放在Shell中:
interleave(["a", "b"], [1, 2, 3, 4])
然后将其返回:
["a", 1, "b", 2, 3, 4]
如果您能帮我,我会非常感激。
我正在尝试编写一个Python函数,它以两个列表作为参数,并将它们交错在一起。组件列表的顺序应该被保留。如果列表长度不同,则较长列表的元素应该出现在结果列表的末尾。 例如,我想把这个放在Shell中:
interleave(["a", "b"], [1, 2, 3, 4])
然后将其返回:
["a", 1, "b", 2, 3, 4]
以下是我使用各种itertools
模块的方法。它适用于任何数量的可迭代对象,而不仅仅是两个:
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)]
然后,您可以通过迭代zipped列表中的每个对中的每个项目来添加项目,省略值为 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