Python混合两个列表的方式

问题描述 投票:9回答:11

我有两个长度为n和n + 1的列表:

[a_1, a_2, ..., a_n]
[b_1, b_2, ..., b_(n+1)]

我想要一个结果给出一个包含两个元素的列表的函数,就是

[b_1, a_1, ..., b_n, a_n, b_(n+1)]

以下内容有效,但看起来并不聪明:

def list_mixing(list_long,list_short):
    list_res = []
    for i in range(len(list_short)):
        list_res.extend([list_long[i], list_short[i]])
    list_res.append(list_long[-1])
    return list_res

任何人都可以建议使用更Python化的方法吗?谢谢!

python
11个回答
12
投票

恕我直言,最好的方法是:

result = [item for sublist in zip(a,b) for item in sublist]

它比求和和归约的方式还快。

UPD对不起,您的第二个列表比一个元素大:)还有另一种疯狂的方式:

result = [item for sublist in map(None, a, b) for item in sublist][:-1]

0
投票

[more-itertools具有roundrobin即可完成工作:


-1
投票

使用邮政编码。这将为您提供一个元组列表,例如:[('a_1','b_1'),('a_2','b_2'),('a_3','b_3')]


16
投票
>>> import itertools
>>> a
['1', '2', '3', '4', '5', '6']
>>> b
['a', 'b', 'c', 'd', 'e', 'f']
>>> list(itertools.chain.from_iterable(zip(a,b)))
['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e', '6', 'f']

zip()产生一个具有最短参数长度的可迭代对象。您可以将a[-1]附加到结果中,也可以将itertools.zip_longest(对于Python 2.x,izip_longest)使用填充值,然后再删除该值。

并且您可以在此解决方案中使用两个以上的输入序列。

为了不附加最后一个值,您可以尝试这种肮脏的方法,但是我并不推荐这样做,尚不清楚:

>>> a
[1, 2, 3, 4, 5]
>>> b
['a', 'b', 'c', 'd', 'e', 'f']
>>> [a[i//2] if i%2 else b[i//2] for i in range(len(a)*2+1)]
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f']

((对于Python 2.x,请使用单个/


4
投票
>>> long = [1, 3, 5, 7]
>>> short = [2, 4, 6]
>>> mixed = []
>>> for i in range(len(long)):
>>>     mixed.append(long[i])
>>>     if i < len(short)
>>>         mixed.append(short[i])
>>> mixed
[1, 2, 3, 4, 5, 6, 7]

3
投票

混合两个列表是zip的工作:

res = []
for a,b in zip(list_long, list_short):
    res += [a,b]

对于不同长度的列表,请定义您自己的功能:

def mix(list_long, list_short):
    result = []
    i,j = iter(list_long), iter(list_short)
    for a,b in zip(i,j):
        res += [a,b]
    for rest in i:
        result += rest
    for rest in j:
        result += rest
    return result

使用answer given by Mihail,我们可以将其缩短为:

def mix(list_long, list_short):
    i,j = iter(list_long), iter(list_short)
    result = [item for sublist in zip(i,j) for item in sublist]
    result += [item for item in i]
    result += [item for item in j]
    return result

2
投票

我将使用以上答案的组合:

>>> a = ['1', '2', '3', '4', '5', '6']

>>> b = ['a', 'b', 'c', 'd', 'e', 'f', 'g']

>>> [i for l in izip_longest(a, b, fillvalue=object) for i in l if i is not object]
<<< ['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e', '6', 'f', 'g']

1
投票
sum([[x,y] for x,y in zip(b,a)],[])+[b[-1]]

注意:这仅适用于给定的列表长度,但可以轻松扩展到任意长度的列表。


1
投票

使用izip_longest填补列表中没有的内容,或不想保留结果。如果您不想保留任何解析为False的内容,请对izip_longestfilter使用默认设置:

from itertools import chain, izip_longest
l1 = [1,3,5]
l2 = [2,4,6,8,10]
filter(None, chain(*izip_longest(l1,l2)))

结果是:[1, 2, 3, 4, 5, 6, 8, 10]

使用None填充间隙并用filter去除它们:

filter(lambda x: x is not None, chain(*izip_longest(l1,l2, fillvalue=None)))

[为了获得更高的效率,当l1l2不是简短列表时,例如非常长或无限的可迭代对象,而不是filter使用ifilter,它将为您提供可迭代对象,而不是将所有内存都放在列表中。示例:

from itertools import chain, izip_longest, ifilter
for value in ifilter(None, chain(*izip_longest(iter1,iter1))):
    print value

0
投票

您可以执行以下操作(假设len(list_long)==len(list_short)+1

def list_mixing(list_long,list_short):
    return [(list_long[i/2] if i%2==0 else list_short[i/2]) for i in range(len(list_long)+len(list_short)]

我将/用于整数除法的位置(确切的运算符取决于语言版本)。>>


0
投票

这是我发现的最好的:

© www.soinside.com 2019 - 2024. All rights reserved.