如何将两个列表的列表压缩成一个列表

23

我有两个列表的列表,每个列表都有相同数量的项。这两个列表看起来像这样:

L1 = [[1, 2], [3, 4], [5, 6]]

L2 =[[a, b], [c, d], [e, f]]

我想创建一个看起来像这样的列表:

Lmerge = [[1, 2, a, b], [3, 4, c, d], [5, 6, e, f]]

我尝试使用zip(),就像这样:

for list1, list2 in zip(*L1, *L2):
    Lmerge = [list1, list2]

如何最好地合并两个列表的列表?提前感谢。

5个回答

24
>>> map(list.__add__, L1, L2)
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

哦哦哦..我更喜欢这个!+1 - Shawn Chin
虽然不是最快的,但肯定是最干净的之一!我仍然支持它。(在下面的一个答案中有基准测试) - Shawn Chin

13
>>> L1 = [[1, 2], [3, 4], [5, 6]]
>>> L2 =[["a", "b"], ["c", "d"], ["e", "f"]]
>>> [x + y for x,y in zip(L1,L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

或者,

>>> [sum(x,[]) for x in zip(L1,L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]
或者,
>>> import itertools
>>> [list(itertools.chain(*x)) for x in zip(L1,L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

我们也可以不使用zip()来实现:

>>> [L1[i] + L2[i] for i in xrange(min(len(L1), len(L2)))]  
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

>>> [x + L2[i] for i, x in enumerate(L1)]  # assuming len(L1) == len(l2)
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

>>> # same as above, but deals with different lengths
>>> Lx, Ly = ((L2,L1), (L1,L2))[len(L1)<=len(L2)] # shortcut for if/else
>>> [x + Ly[i] for i, x in enumerate(Lx)]

一些基准测试

以下是到目前为止提供的答案的一些基准测试结果。

看起来最流行的答案 ([x + y for x,y in zip(L1,L2)]) 和 @hammar的map解决方案差不多。 另一方面,我提供的替代解决方案已被证明是垃圾!

然而,目前最快的解决方案似乎是使用没有zip()的列表推导式的方案。

[me@home]$ SETUP="L1=[[x,x+1] for x in xrange(10000)];L2=[[x+2,x+3] for x in xrange(10000)]"

[me@home]$ # this raises IndexError if len(L1) > len(L2)
[me@home]$ python -m timeit "$SETUP" "[x + L2[i] for i, x in enumerate(L1)]"
100 loops, best of 3: 10.6 msec per loop

[me@home]$ # same as above, but deals with length inconsistencies
[me@home]$ python -m timeit "$SETUP" "Lx,Ly=((L2,L1),(L1,L2))[len(L1)<=len(L2)];[x + Ly[i] for i, x in enumerate(Lx)]"
100 loops, best of 3: 10.6 msec per loop

[me@home]$ # almost as fast as above, but easier to read
[me@home]$ python -m timeit "$SETUP" "[L1[i] + L2[i] for i in xrange(min(len(L1),len(L2)))]"
100 loops, best of 3: 10.8 msec per loop

[me@home]$ python -m timeit "$SETUP" "L3=[x + y for x,y in zip(L1,L2)]"
100 loops, best of 3: 13.4 msec per loop

[me@home]$ python -m timeit "$SETUP" "L3=map(list.__add__, L1, L2)" 
100 loops, best of 3: 13.5 msec per loop

[me@home]$ python -m timeit "$SETUP" "L3=[sum(x,[]) for x in zip(L1,L2)]"
100 loops, best of 3: 18.1 msec per loop

[me@home]$ python -m timeit "$SETUP;import itertools" "L3=[list(itertools.chain(*x)) for x in zip(L1,L2)]"
10 loops, best of 3: 32.9 msec per loop

@Zac的建议非常快速,但这样比较起来就像是苹果和橙子,因为它在L1上执行了一个列表扩展的原地操作,而不是创建第三个列表。所以,如果L1不再需要,这是一个很好的解决方案。

[me@home]$ python -m timeit "$SETUP" "for index, x in enumerate(L1): x.extend(L2[index])"
100 loops, best of 3: 9.46 msec per loop

然而,如果需要保持L1不变,则包括深度复制后性能会变得次优。

[me@home]$ python -m timeit "$SETUP;from copy import deepcopy" "L3=deepcopy(L1)
> for index, x in enumerate(L1): x.extend(L2[index])"
10 loops, best of 3: 116 msec per loop

4
你希望使用加号运算符将子列表组合起来,并在列表推导式中对它们进行迭代:
Lmerge = [i1 + i2 for i1, i2 in zip(L1, L2)]

1
L1 = [[1, 2], [3, 4], [5, 6]]
L2 =[[a, b], [c, d], [e, f]]

Lmerge = [x + y for x, y in zip(L1, L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

1
for index, x in enumerate(L1):
    x.extend(L2[index])

1
不错的解决方案,但它改变了 L1 而不是创建一个新列表,所以关键在于是否仍需要使用 L1 - Shawn Chin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接