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


2524

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

例:

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

预期结果:

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

6
您是否只想追加,还是要按排序顺序合并两个列表?您期望[1,3,6]和[2,4,5]的输出是什么?我们是否可以假设两个子列表都已排序(如您的示例所示)?
smci 2015年

1
...如果列表有重复也该怎么[1,2,5] and [2,4,5,6]办?您是否希望包含,排除或忽略重复项?
smci

Answers:


3898

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

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

joinedlist = listone + listtwo

输出:

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

109
这会创建listone的深层副本并追加listtwo吗?
Daniel F

152
@Daniel它将创建一个新列表,其中第一个列表中的项目为浅表副本,然后是第二个列表中的项目的浅表副本。使用copy.deepcopy获取列表的深层副本。
丹尼尔·G

219
此处的另一个有用细节:listone += listtwo结果listone == [1, 2, 3, 4, 5, 6]
rickcnagy 2014年

16
@ br1ckb0t会改变listone指向的内容吗?因此:list3 = listone listone+=listtwo list3也被更改了吗?
MikeH

11
它确实改变了list3。但是,如果这不是问题,则添加两个列表而不是创建一个新列表更容易阅读。
rickcnagy

316

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

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

4
chain对于两个列表,速度较慢(但不是很多),但是对于链接多个列表(n >> 2),这是最快的解决方案。
cs95

@ cs95比什么慢?
Moberg

@Moberg与其他串联列表的方法相比,请参考此处的基准以供参考。
cs95

262

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

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

当在Python中使用加星标的表达式时,PEP的标题为Additional Unpacking Generalizations,通常会减少一些语法限制*。使用它,现在还可以使用以下方法来加入两个列表(适用于任何可迭代对象):

>>> 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)现在等同于just)的可读性更高,也很有用[*my_list, *my_tuple, *my_range]

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

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

以下内容不会:

res = [*l, *r]

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


1
在可迭代类型上使用拆包方法的一个很好的例子是函数,该函数在要连接的列表之一上返回迭代器。例如,您可以颠倒要连接的列表之一:res = [*l1, *reversed(l2)]。由于reversed返回迭代器,res = l1 + reversed(l2)将引发错误。
阿兰(alan)

2
值得注意的是,这类似于在python中组合字典。dict3 = {** dict1,** dict2}。请注意,我们使用**解包字典,而使用列表则使用*解包。
凯文S

212

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

mergedlist = list(set(listone + listtwo))

45
是的,但是,如果您对此感兴趣,它也会删除重复项。添加列表不会这样做。
2012年

1
如何做到这一点并保留订购信息?
纳蒂姆2013年

11
胜于listone + [x for x in listtwo if x not in listone]
Natim

8
+1恕我直言,这是“合并”(联合)列表的正确方法,而“批准的”答案描述了如何合并/添加列表(多组)
alfasin 2014年

2
如果您关心保持输入顺序,则import collections; mergedlist = list(collections.OrderedDict.fromkeys(listone + listtwo))可以解决问题。
SethMMorton '16

185

您也可以使用list.extend()方法将a添加list到另一个的结尾:

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

listone.extend(listtwo)

如果要保持原始列表完整无缺,则可以创建一个新list对象,并且extend两个列表都指向该对象:

mergedlist = []
mergedlist.extend(listone)
mergedlist.extend(listtwo)

80

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

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

在此处输入图片说明

脚注

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

  2. 查看chain 和阅读 chain.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方法就地操作,因此每次测试前都必须生成一个副本。为了公平起见,所有方法在左侧列表中都有一个预复制步骤,可以忽略。


对其他解决方案的评论

  • 请勿list.__add__以任何方式,形状或形式直接使用DUNDER方法。实际上,请避免使用dunder方法,并使用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)单一功能调用和惯用语言更加罗word,并且速度更慢。append之所以变慢,是因为为列表分配和增长了内存的语义。参见此处进行类似的讨论。

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

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

  • operator.add(a, b)是可以接受的等效功能a + b。它的用例主要用于动态方法分派。否则,在我看来,最好选择更a + b短,更易读的格式。YMMV。


stackoverflow.com/q/36863404/125507的答案可以使用perfplot图(包括numba解决方案)
endolith,

@endolith忙得不可开交,但我看一下是否可以加入。Ty。
cs95

哪种方法最好,然后是性能明智的方法,更快的方法?请告诉。
ganeshdeshmukh

@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.“解决方案不是在我的回答中列出,或在critized‘评论’,我建议不要使用。
cs95


51

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

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

>>> 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]

请注意,这在ais []或时也可以正常使用[[1,2,3]]

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

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

如果不需要a list,而只是需要迭代,请省略list()

更新资料

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

sum(a, [])

3
Python 3 note:reduce现在已经存在,functools因此您需要首先将其导入。
Dimitris Fasarakis Hilliard

41

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

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))

最后一部分可以任意重新排序项目。如果您想保留订单,可以在CPython 3.6+上执行list(dict.fromkeys(a + b))
Boris

27

值得注意的是,该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则可以使用class方法:

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

22

使用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(等效)而不是定义自己的函数。
鲍里斯(Boris)

18

如果你想在排序的形式两个列表合并,您可以使用merge从函数heapq库。

from heapq import merge

a = [1, 2, 4]
b = [2, 4, 6, 7]

print list(merge(a, b))

15

如果您不能使用加号(+),则可以使用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]

3
抢劫邓迪通常不是最好的方法。如果+不在桌子上,请使用operator.add
Dimitris Fasarakis Hilliard'7

2
为什么加号运算符不可用?
cs01

2
通常不会:),但是如果您要使用map函数进行列表串联或要将add函数存储在变量中,则不能使用+。
jpihl

13

作为更多列表的更通用方法,您可以将它们放在列表中并使用itertools.chain.from_iterable()1函数,该函数基于答案是扁平化嵌套列表的最佳方法:

>>> 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)


10

如果您需要使用复杂的排序规则合并两个有序列表,则可能需要像下面的代码一样滚动它(使用简单的排序规则以提高可读性:-))。

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
cs95


7
list(set(listone) | set(listtwo))

上面的代码不保留顺序,而是从每个列表中删除重复项(但不从串联列表中删除)


6

正如许多人已经指出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
        [...]

这里要理解的要点是,列表只是可迭代的特例,它们是与其他对象一样的对象。并且for ... inpython 中的循环可以使用元组变量,因此同时循环多个变量很简单。


5

使用简单的列表理解:

joined_list = [item for list_ in [list_one, list_two] for item in list_]

它具有使用附加解包概括的最新方法的所有优点-即您可以以这种方式连接任意数量的不同可迭代对象(例如,列表,元组,范围和生成器)-而且不限于Python 3.5或更高版本。


4

合并列表列表的一种非常简洁的方法是

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而是使用。这是比较罗word的等效词,sum(list_of_lists, [])同样是糟糕的。不使用!
cs95

@ cs95您可以使用list来解释问题吗。__add__
Akash Singh,

dunder方法是“私有方法”,通常不应直接使用(它们由其他函数调用)。obj.__class__和是例外obj.__dict__
cs95


2

因此,有两种简单的方法。

  1. 使用+:它从提供的列表中创建一个新列表

例:

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
  1. 使用extend:将新列表追加到现有列表。这意味着它不会创建单独的列表。

例:

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是有效的。


2
如果我需要添加多个列表,例如a + b + c + d + e,该怎么办?
Tweakimp

2
@Tweakimp请参阅此答案,其中有两个选项(我建议chain.from_iterable)。
cs95

2

有多种方法可以在python中串联列表。

l1 = [1,2,3,4]
l2 = [3,4,5,6]

1. new_list = l1.extend(l2)
2. new_list = l1 + l2
3. new_list = [*l1, *l2]

1
您能否解释一下该答案提供的其他新信息?
cs95

有多种方法可以在python中串联列表 -在其他更老的答案中对此进行了广泛讨论。这会提供什么新信息?
Tomerikoo

-1
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]

-1

如果您想要一个新列表,同时保留两个旧列表:

def concatenate_list(listOne, listTwo):
    joinedList = []
    for i in listOne:
        joinedList.append(i)
    for j in listTwo:
        joinedList.append(j)

    sorted(joinedList)

    return joinedList

如何不同于此答案由王明孝?
Tomerikoo

-2
lst1 = [1,2]

lst2 = [3,4]

def list_combinationer(Bushisms, are_funny):

    for item in lst1:
        lst2.append(item)
        lst1n2 = sorted(lst2)
        print lst1n2

list_combinationer(lst1, lst2)

[1,2,3,4]

4
那么,请做一些解释
U10转发

如果在函数内部使用全局名称,该函数的参数有什么意义?
Tomerikoo

-2

您可以按照代码进行操作

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

for i in listone:
    listtwo.append(i)
print(listtwo)

[1,2,3,4,5,6]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.