如何在 Python 中连接两个列表?
Posted
技术标签:
【中文标题】如何在 Python 中连接两个列表?【英文标题】:How do I concatenate two lists in Python? 【发布时间】:2010-12-15 18:42:35 【问题描述】:例子:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
预期结果:
>>> joinedlist
[1, 2, 3, 4, 5, 6]
【问题讨论】:
您想要简单地追加,还是想要按排序顺序合并两个列表?您期望 [1,3,6] 和 [2,4,5] 的输出是什么?我们可以假设两个子列表都已排序(如您的示例中所示)吗? ...如果列表有重复项,例如[1,2,5] and [2,4,5,6]
?您希望包含、排除还是不关心重复项?
如果有人觉得有用的话,我制作了一个关于连接列表的 6 种方法的 youtube 教程youtube.com/watch?v=O5kJ1v9XrDw
【参考方案1】:
只需添加这两个列表:
final_list = list1 + list2
【讨论】:
虽然这可能会回答他的问题,但最好多解释一下 e。 G。添加一些代码。【参考方案2】:对于列表数量较少的情况,您可以简单地将列表添加在一起或使用就地解包(在 Python-3.5+ 中可用):
In [1]: listone = [1, 2, 3]
...: listtwo = [4, 5, 6]
In [2]: listone + listtwo
Out[2]: [1, 2, 3, 4, 5, 6]
In [3]: [*listone, *listtwo]
Out[3]: [1, 2, 3, 4, 5, 6]
对于列表数量更多的情况,您可以使用chain.from_iterable()
1 模块中的itertools
函数作为更通用的方法。另外,基于this answer,这个功能是最好的;或者至少也是扁平化嵌套列表的一种非常好的方法。
>>> l=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> import itertools
>>> list(itertools.chain.from_iterable(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
1. 请注意,`chain.from_iterable()` 在 Python 2.6 及更高版本中可用。在其他版本中,使用 `chain(*l)`。
【讨论】:
【参考方案3】:提供的解决方案适用于单个列表。如果列表中有列表并且需要合并相应的列表。通过 for 循环的“+”操作完成了工作。
a=[[1,2,3],[4,5,6]]
b=[[0,1,2],[7,8,9]]
for i in range(len(a)):
cc.append(a[i]+b[i])
输出:[[1, 2, 3, 0, 1, 2], [4, 5, 6, 7, 8, 9]]
【讨论】:
【参考方案4】:我推荐三种方法来连接列表,但最推荐第一种方法,
# easiest and least complexity method <= recommended
listone = [1, 2, 3]
listtwo = [4, 5, 6]
newlist = listone + listtwo
print(newlist)
# 2nd easiest method
newlist = listone.copy()
newlist.extend(listtwo)
print(newlist)
在第二种方法中,我将newlist
分配给listone
的副本,因为我不想更改listone
。
# 3rd method
newlist = listone.copy()
for j in listtwo:
newlist.append(j)
print(newlist)
这不是连接列表的好方法,因为我们使用 for 循环来连接列表。所以时间复杂度比其他两种方法要高很多。
【讨论】:
【参考方案5】:您可以使用+
运算符来组合它们:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
joinedlist = listone + listtwo
输出:
>>> joinedlist
[1, 2, 3, 4, 5, 6]
【讨论】:
这会创建 listone 的深层副本并附加 listtwo 吗? @Daniel 它将创建一个新列表,其中包含第一个列表中项目的浅表副本,然后是第二个列表中项目的浅表副本。使用 copy.deepcopy 获取列表的深层副本。 这里还有一个有用的细节:listone += listtwo
导致listone == [1, 2, 3, 4, 5, 6]
@br1ckb0t 这会改变listone 指向的内容吗?所以:list3 = listone
listone+=listtwo
list3 也改了吗?
它确实改变了 list3。但是,如果这不是问题,添加两个列表而不是创建一个新列表会更简单、更易读。【参考方案6】:
您也可以只使用sum
。
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> sum([a, b], [])
[1, 2, 3, 4, 5, 6]
>>>
这适用于任何长度和任何元素类型的列表:
>>> a = ['a', 'b', 'c', 'd']
>>> b = [1, 2, 3, 4]
>>> c = [1, 2]
>>> sum([a, b, c], [])
['a', 'b', 'c', 'd', 1, 2, 3, 4, 1, 2]
>>>
我之所以添加[]
,是因为start
参数默认设置为0
,所以它会循环遍历列表并添加到start
,但是0 + [1, 2, 3]
会报错,所以如果我们将start
设置为[]
,它将添加到[]
,[] + [1, 2, 3]
将按预期工作。
【讨论】:
【参考方案7】:你可以使用.extend
方法
listone = [1, 2, 3]
listtwo = [4, 5, 6]
listone.extend(lsittwo)
现在,当你这样做时,
print(listone)
你会有这份清单,
[1,2,3,4,5,6]
【讨论】:
【参考方案8】:另一种方式:
>>> listone = [1, 2, 3]
>>> listtwo = [4, 5, 6]
>>> joinedlist = [*listone, *listtwo]
>>> joinedlist
[1, 2, 3, 4, 5, 6]
>>>
【讨论】:
【参考方案9】:你可以在python中使用union()函数。
joinedlist = union(listone, listtwo)
print(joinedlist)
本质上,这是在删除两个列表中的每个重复项之一。由于您的列表没有任何重复项,因此它只返回两个列表的连接版本。
【讨论】:
union
不适用于列表,您可以将其与集合或字典一起使用
哦,是的,对不起,我好久没用了,我的坏【参考方案10】:
我假设您想要以下两种方法之一:
保留重复元素
很简单,像字符串一样拼接:
def concat_list(l1,l2):
l3 = l1+l2
return l3
下一步如果要消除重复元素
def concat_list(l1,l2):
l3 = []
for i in [l1,l2]:
for j in i:
if j not in l3:
#Check if element exists in final list, if no then add element to list
l3.append(j)
return l3
【讨论】:
【参考方案11】:如果您使用的是 NumPy,您可以使用以下命令连接两个兼容维度的数组:
numpy.concatenate([a,b])
【讨论】:
@cs95 它也不会“不要求”numpy。我应该说这实际上对我有帮助,因为加号运算符不适用于我的应用程序【参考方案12】:如何在 Python 中连接两个列表?
从 3.9 开始,这些是最流行的 stdlib 方法,用于在 python 中连接两个(或更多)列表。
脚注
这是一个巧妙的解决方案,因为它简洁。但是
sum
以成对的方式执行连接,这意味着这是一个 二次运算作为内存必须为每一步分配。做 如果您的列表很大,请勿使用。见
chain
和chain.from_iterable
从文档。您需要先import itertools
。 连接在内存中是线性的,所以这是最好的 性能和版本兼容性。chain.from_iterable
在 2.6 中引入。此方法使用Additional Unpacking Generalizations (PEP 448),但不能 推广到 N 个列表,除非您自己手动解压缩每个列表。
a += b
和a.extend(b)
在所有实际用途中或多或少是等效的。+=
在列表上调用时将在内部调用list.__iadd__
,它将第一个列表扩展了第二个。
性能
2 列表连接1
这些方法之间没有太大区别,但考虑到它们都具有相同的复杂顺序(线性),这是有道理的。除了风格问题,没有什么特别的理由偏爱其中一个。
N-List 连接
绘图已使用perfplot 模块生成。 Code, for your reference.
1。 iadd
(+=
) 和extend
方法就地运行,因此每次测试前都必须生成一个副本。为了公平起见,所有方法都有一个可以忽略左侧列表的预复制步骤。
对其他解决方案的评论
请勿以任何方式、形状或形式直接使用 DUNDER 方法list.__add__
。事实上,不要使用 dunder 方法,并像设计它们一样使用运算符和 operator
函数。 Python 有仔细的语义,这些语义比直接调用 dunder 更复杂。这是an example。所以,总而言之,a.__add__(b)
=> BAD; 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
速度较慢,因为为列表分配和增长内存的语义。类似的讨论请参见here。
heapq.merge
可以工作,但它的用例是在线性时间内合并排序列表。在任何其他情况下使用它都是一种反模式。
yield
从函数中列出元素是一种可接受的方法,但chain
这样做更快更好(它在 C 中有一个代码路径,所以速度很快)。
operator.add(a, b)
是可接受的功能等效于a + b
。它的用例主要用于动态方法分派。否则,更喜欢a + b
,它更短、更易读,在我看来。 YMMV。
【讨论】:
***.com/q/36863404/125507 的答案可以使用 perfplot 图(包括 numba 解决方案) @endolith 有点忙于工作,但我会看看我是否可以加入。Ty。 哪个是最好的方法,然后性能明智,速度更快?请告诉。 @ganeshdeshmukh TL;DR 是他们都很好,你选择哪一个主要是风格问题。"There's not much difference between these methods but that makes sense given they all have the same order of complexity (linear). There's no particular reason to prefer one over the other except as a matter of style.
" 我的答案中未列出的解决方案,或在“评论”中批评的解决方案,我建议不要使用。【参考方案13】:
a=[1,2,3]
b=[4,5,6]
c=a+b
print(c)
输出:
>>> [1, 2, 3, 4, 5, 6]
在上面的代码中,“+”运算符用于将两个列表连接成一个列表。
另一种解决方案:
a=[1,2,3]
b=[4,5,6]
c=[] #Empty list in which we are going to append the values of list (a) and (b)
for i in a:
c.append(i)
for j in b:
c.append(j)
print(c)
输出:
>>> [1, 2, 3, 4, 5, 6]
【讨论】:
【参考方案14】:您还可以使用list.extend()
方法在另一个末尾添加list
:
listone = [1,2,3]
listtwo = [4,5,6]
listone.extend(listtwo)
如果您想保持原始列表不变,您可以创建一个新的list
对象,并将extend
两个列表都添加到它:
mergedlist = []
mergedlist.extend(listone)
mergedlist.extend(listtwo)
【讨论】:
为什么在我的情况下这个方法返回None
?
listone = [1,2,3]; listtwo = [4,5,6]; listone.extend(listtwo)
这返回给我None
它对listone
进行了就地更新。所以检查列表中的listone
实际上我正在返回一个表达式,我正在使用您提到的方法扩展列表。我没有像this 帖子中所说的那样重新分配列表。我的表达式类似于return list1.extend(list2)
,这个表达式返回None
给我。【参考方案15】:
还可以创建一个生成器,使用itertools.chain()
简单地迭代两个列表中的项目。这允许您将列表(或任何可迭代的)链接在一起进行处理,而无需将项目复制到新列表:
import itertools
for item in itertools.chain(listone, listtwo):
# Do something with each list item
【讨论】:
chain
对于两个列表来说速度较慢(但不是很多),但对于链接多个列表 (n >> 2) 来说是最快的解决方案。
@cs95 比什么慢?
@Moberg 与其他连接列表的方式相比,参考请看我的基准测试here。【参考方案16】:
Python >= 3.5
替代:[*l1, *l2]
通过接受 PEP 448
引入了另一个替代方案,值得一提。
标题为 Additional Unpacking Generalizations 的 PEP 通常减少了在 Python 中使用星号 *
表达式时的一些语法限制;有了它,现在也可以加入两个列表(适用于任何可迭代):
>>> 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
。
【讨论】:
处理可迭代类型的解包方法的一个很好的例子是函数返回一个迭代器,该迭代器覆盖您要连接的列表之一。例如,您可以反转您要连接的列表之一:res = [*l1, *reversed(l2)]
。由于reversed
返回一个迭代器,res = l1 + reversed(l2)
会抛出一个错误。
值得注意的是,这类似于在python中组合字典。 dict3 = **dict1, **dict2。请注意,我们使用 ** 解包字典,而列表使用 * 解包。
我的语法nazy必须指出:*字典【参考方案17】:
如果不能使用加号运算符 (+
),可以使用 operator
导入:
import operator
listone = [1,2,3]
listtwo = [4,5,6]
result = operator.add(listone, listtwo)
print(result)
>>> [1, 2, 3, 4, 5, 6]
或者,您也可以使用__add__
dunder 函数:
listone = [1,2,3]
listtwo = [4,5,6]
result = list.__add__(listone, listtwo)
print(result)
>>> [1, 2, 3, 4, 5, 6]
【讨论】:
抓取垃圾通常不是最好的方法。如果+
不在讨论范围内,请使用operator.add
。
为什么加号运算符不可用?
通常不会:) 但是如果您正在使用 map 函数进行列表连接或想要将 add 函数存储在变量中,则不能使用 +。【参考方案18】:
使用简单的列表推导:
joined_list = [item for list_ in [list_one, list_two] for item in list_]
它具有使用 Additional Unpacking Generalizations 的最新方法的所有优点 - 即您可以通过这种方式连接任意数量的不同迭代(例如,列表、元组、范围和生成器) - 而且它不限于 Python 3.5 或更高版本。
【讨论】:
【参考方案19】:所以有两种简单的方法。
-
使用
+
:它从提供的列表中创建一个新列表
例子:
In [1]: a = [1, 2, 3]
In [2]: b = [4, 5, 6]
In [3]: a + b
Out[3]: [1, 2, 3, 4, 5, 6]
In [4]: %timeit a + b
10000000 loops, best of 3: 126 ns per loop
-
使用扩展:它将新列表附加到现有列表。这意味着它不会创建单独的列表。
例子:
In [1]: a = [1, 2, 3]
In [2]: b = [4, 5, 6]
In [3]: %timeit a.extend(b)
10000000 loops, best of 3: 91.1 ns per loop
因此我们看到,在两种最流行的方法中,extend
是有效的。
【讨论】:
如果我需要添加多个列表,比如a+b+c+d+e怎么办? @Tweakimp 查看this answer,它有几个选项(我推荐chain.from_iterable
)。【参考方案20】:
如果您想以排序形式合并两个列表,可以使用heapq
库中的merge
函数。
from heapq import merge
a = [1, 2, 4]
b = [2, 4, 6, 7]
print list(merge(a, b))
【讨论】:
【参考方案21】:这很简单,我想它甚至显示在the tutorial:
>>> listone = [1,2,3]
>>> listtwo = [4,5,6]
>>>
>>> listone + listtwo
[1, 2, 3, 4, 5, 6]
【讨论】:
【参考方案22】:这个问题直接询问加入两个列表。但是,即使您正在寻找一种加入多个列表的方法(包括加入零个列表的情况),它的搜索量也相当高。
我认为最好的选择是使用列表推导:
>>> 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()
。
更新
Patrick Collins 在 cmets 中建议的替代方案也可以为您工作:
sum(a, [])
【讨论】:
Python 3 注意:reduce
现在在 functools
中,因此您需要先导入它。【参考方案23】:
组合列表列表的一种非常简洁的方法是
list_of_lists = [[1,2,3], [4,5,6], [7,8,9]]
reduce(list.__add__, list_of_lists)
这给了我们
[1, 2, 3, 4, 5, 6, 7, 8, 9]
【讨论】:
请不要使用list.__add__
,而是使用operator.add
。这是sum(list_of_lists, [])
的更冗长的等价物,同样糟糕。不要使用!
@cs95 你能解释一下使用 list.__add__ 是什么问题
dunder 方法是“私有方法”,通常不应直接使用(它们由其他函数调用)。 obj.__class__
和 obj.__dict__
除外。
如果__add__
看起来太低级和不稳定(容易改变),你可以使用np.union1d
代替。【参考方案24】:
import itertools
A = list(zip([1,3,5,7,9],[2,4,6,8,10]))
B = [1,3,5,7,9]+[2,4,6,8,10]
C = list(set([1,3,5,7,9] + [2,4,6,8,10]))
D = [1,3,5,7,9]
D.append([2,4,6,8,10])
E = [1,3,5,7,9]
E.extend([2,4,6,8,10])
F = []
for a in itertools.chain([1,3,5,7,9], [2,4,6,8,10]):
F.append(a)
print ("A: " + str(A))
print ("B: " + str(B))
print ("C: " + str(C))
print ("D: " + str(D))
print ("E: " + str(E))
print ("F: " + str(F))
输出:
A: [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
B: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
C: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
D: [1, 3, 5, 7, 9, [2, 4, 6, 8, 10]]
E: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
F: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
【讨论】:
【参考方案25】:list(set(listone) | set(listtwo))
上述代码不保留顺序,从每个列表中删除重复项(但不是从串联列表中)
【讨论】:
【参考方案26】:您可以使用在list
对象上定义的append()
方法:
mergedlist =[]
for elem in listone:
mergedlist.append(elem)
for elem in listtwo:
mergedlist.append(elem)
【讨论】:
只是让你知道,如果这是你在实践中所做的,这比其他提议的方法要慢得多。见***.com/questions/17479361/…【参考方案27】:正如许多人已经指出的那样,itertools.chain()
是如果需要对两个列表应用完全相同的处理的方法。就我而言,我有一个标签和一个标志,它们与一个列表不同,所以我需要一些稍微复杂一些的东西。事实证明,在幕后 itertools.chain()
只是做了以下事情:
for it in iterables:
for element in it:
yield element
(见https://docs.python.org/2/library/itertools.html),所以我从这里得到灵感,写了一些类似的东西:
for iterable, header, flag in ( (newList, 'New', ''), (modList, 'Modified', '-f')):
print header + ':'
for path in iterable:
[...]
command = 'cp -r' if os.path.isdir(srcPath) else 'cp'
print >> SCRIPT , command, flag, srcPath, mergedDirPath
[...]
这里要理解的要点是,列表只是可迭代的一个特例,它和其他对象一样是对象;并且python中的for ... in
循环可以处理元组变量,因此同时循环多个变量很简单。
【讨论】:
【参考方案28】:使用 Python 3.3+ 你可以使用yield from:
listone = [1,2,3]
listtwo = [4,5,6]
def merge(l1, l2):
yield from l1
yield from l2
>>> list(merge(listone, listtwo))
[1, 2, 3, 4, 5, 6]
或者,如果您想支持任意数量的迭代器:
def merge(*iters):
for it in iters:
yield from it
>>> list(merge(listone, listtwo, 'abcd', [20, 21, 22]))
[1, 2, 3, 4, 5, 6, 'a', 'b', 'c', 'd', 20, 21, 22]
【讨论】:
你可以使用itertools.chain
(相当于)而不是定义你自己的函数。【参考方案29】:
您可以使用集合来获取唯一值的合并列表
mergedlist = list(set(listone + listtwo))
【讨论】:
没错,但是,如果您对此感兴趣,它也会删除重复项。列表添加不会这样做。 有什么方法可以做到这一点并保留订购信息? 优于listone + [x for x in listtwo if x not in listone]
+1 恕我直言,这是“合并”(联合)列表的正确方法,而“已批准”的答案描述了如何组合/添加列表(多集)
如果您关心维护输入顺序,那么import collections; mergedlist = list(collections.OrderedDict.fromkeys(listone + listtwo))
就可以解决问题。【参考方案30】:
如果您需要合并具有复杂排序规则的两个有序列表,您可能必须像下面的代码一样自己滚动它(使用简单的排序规则来提高可读性:-))。
list1 = [1,2,5]
list2 = [2,3,4]
newlist = []
while list1 and list2:
if list1[0] == list2[0]:
newlist.append(list1.pop(0))
list2.pop(0)
elif list1[0] < list2[0]:
newlist.append(list1.pop(0))
else:
newlist.append(list2.pop(0))
if list1:
newlist.extend(list1)
if list2:
newlist.extend(list2)
assert(newlist == [1, 2, 3, 4, 5])
【讨论】:
或者直接使用heapq.merge
。以上是关于如何在 Python 中连接两个列表?的主要内容,如果未能解决你的问题,请参考以下文章