如何在 Python 中串联两个列表?

如何在 Python 中串联两个列表?

例:

listone = [1, 2, 3]
listtwo = [4, 5, 6]

预期结果:

>>> joinedlist
[1, 2, 3, 4, 5, 6]

答案

您可以使用+运算符组合它们:

listone = [1,2,3]
listtwo = [4,5,6]

joinedlist = listone + listtwo

输出:

>>> joinedlist
[1,2,3,4,5,6]

也可以创建一个生成器,使用itertools.chain()简单地遍历两个列表中的项目。这使您可以将列表(或任何可迭代的)链接在一起进行处理,而无需将项目复制到新列表中:

import itertools
for item in itertools.chain(listone, listtwo):
    # Do something with each list item

Python >= 3.5替代: [*l1, *l2]

值得一提的是,通过接受PEP 448引入了另一种选择。

当在 Python 中使用带星号*表达式时,PEP 的标题为 “ 其他解包概述” 通常会减少一些语法上的限制;有了它,加入两个列表(适用于任何可迭代对象)现在也可以使用:

>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> joined_list = [*l1, *l2]  # unpack both iterables in a list literal
>>> print(joined_list)
[1, 2, 3, 4, 5, 6]

此功能是为 Python 3.5定义的,尚未反向移植到3.x系列的先前版本。在不受支持的版本中,将引发SyntaxError

与其他方法一样,这也会在相应列表中创建元素的浅表副本


这种方法的好处是,您实际上不需要列表即可执行它,任何可迭代的操作都可以。如 PEP 中所述:

这对于将可迭代项求和到列表中(例如my_list + list(my_tuple) + list(my_range) ,现在也等效于[*my_list, *my_tuple, *my_range]

因此,虽然加上+会由于类型不匹配而引发TypeError

l = [1, 2, 3]
r = range(4, 7)
res = l + r

以下内容不会:

res = [*l, *r]

因为它首先将可迭代对象的内容解包,然后仅从内容中创建一个list

您可以使用集合来获取唯一值的合并列表

mergedlist = list(set(listone + listtwo))

您还可以使用extend来将list添加到另一个list的末尾:

listone = [1,2,3]
listtwo = [4,5,6]
mergedlist = []
mergedlist.extend(listone)
mergedlist.extend(listtwo)

这很简单,我认为它甚至在本教程中已显示:

>>> listone = [1,2,3]
>>> listtwo = [4,5,6]
>>>
>>> listone + listtwo
[1, 2, 3, 4, 5, 6]

这个问题直接询问有关加入两个列表的问题。但是,即使您正在寻找加入许多列表的方式(包括加入零列表的情况),其搜索量也很高。

我认为最好的选择是使用列表推导:

>>> a = [[1,2,3], [4,5,6], [7,8,9]]
>>> [x for xs in a for x in xs]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

您还可以创建生成器:

>>> map(str, (x for xs in a for x in xs))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

旧答案

考虑这种更通用的方法:

a = [[1,2,3], [4,5,6], [7,8,9]]
reduce(lambda c, x: c + x, a, [])

将输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

注意,当a[][[1,2,3]]时,这也可以正常使用。

但是,可以使用itertools更有效地完成此操作:

a = [[1,2,3], [4,5,6], [7,8,9]]
list(itertools.chain(*a))

如果您不需要list ,而只是一个可迭代的list() ,请省略list()

更新资料

Patrick Collins 在评论中建议的替代方法也可能对您有用:

sum(a, [])

如何在 Python 中串联两个列表?

从 3.7 开始,这些是在 python 中串联两个(或多个)列表的最受欢迎的 stdlib 方法。

在此处输入图片说明

脚注

  1. 由于它的简洁性,这是一个不错的解决方案。但是sum以成对方式执行级联,这意味着这是二次运算,因为必须为每个步骤分配内存。如果您的列表很大,请不要使用。

  2. 请参阅文档中的chainchain.from_iterable 。您将需要首先import itertools 。串联在内存中是线性的,因此这在性能和版本兼容性方面是最佳的。 chain.from_iterable已在 2.6 中引入。

  3. 此方法使用 “ 其他解包概述”(PEP 448) ,但除非您手动手动解压缩每个列表,否则无法将其归纳为 N 个列表。

  4. 对于所有实际目的, a += ba.extend(b)相等。 +=在列表上调用时会在内部调用list.__iadd__ ,它将第一个列表扩展到第二个列表。


性能

2 列表串联 1

在此处输入图片说明

N 列表串联

在此处输入图片说明

使用perfplot模块已生成图。 代码,供您参考。

1. iadd+= )和extend方法就地操作,因此每次测试之前都必须生成一个副本。为了公平起见,所有方法在左侧列表中都有一个预复制步骤,可以忽略。


对其他解决方案的评论

  • 请勿以任何方式,形状或形式直接使用 DUNDER METHOD list.__add__ 。实际上,请避免使用笨拙的方法,并使用设计用于它们的运算符和operator功能。 Python 具有仔细的语义,这些语义比直接调用 dunder 更复杂。这是一个例子 。因此,总而言之, a.__add__(b) => 不好; a + b => 良好。

  • 这里的一些答案为成对串联提供了reduce(operator.add, [a, b]) - 这与sum([a, b], [])只是更加冗长。

  • 使用set任何方法都将删除重复项并失去顺序。请谨慎使用。

  • for i in b: a.append(i)a.extend(b)a.extend(b) ,也更慢,后者是单个函数调用,更惯用。 append的速度较慢,这是因为为列表分配和增长了内存的语义。参见此处进行类似的讨论。

  • heapq.merge可以使用,但是它的用例是在线性时间内合并排序后的列表。在任何其他情况下使用它都是一种反模式。

  • 从函数中yield列表元素是一种可以接受的方法,但是chain可以更快更好地做到这一点(它在 C 中具有代码路径,因此速度很快)。

  • operator.add(a, b)是等效于a + b 。它的用例主要用于动态方法分派。否则, 我认为 a + b较短且可读性更好。 YMMV。

您可以简单地使用++=运算符,如下所示:

a = [1, 2, 3]
b = [4, 5, 6]

c = a + b

要么:

c = []
a = [1, 2, 3]
b = [4, 5, 6]

c += (a + b)

另外,如果您希望合并列表中的值唯一,则可以执行以下操作:

c = list(set(a + b))

值得注意的是, itertools.chain函数接受可变数量的参数:

>>> l1 = ['a']; l2 = ['b', 'c']; l3 = ['d', 'e', 'f']
>>> [i for i in itertools.chain(l1, l2)]
['a', 'b', 'c']
>>> [i for i in itertools.chain(l1, l2, l3)]
['a', 'b', 'c', 'd', 'e', 'f']

如果输入一个可迭代的(元组,列表,生成器等),则可以使用from_iterable类方法:

>>> il = [['a'], ['b', 'c'], ['d', 'e', 'f']]
>>> [i for i in itertools.chain.from_iterable(il)]
['a', 'b', 'c', 'd', 'e', 'f']