ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Python 中连接两个列表?

这个问题的答案是社区的努力。编辑现有答案以改进这篇文章。它目前不接受新的答案或交互。

如何在 Python 中连接两个列表?

例子:

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

M
Mateen Ulhaq

使用 + 运算符组合列表:

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 是否也发生了变化?
@Pygmalion 这不是 Python3 特定的,而是特定于 NumPy 数组如何处理运算符的。请参阅 Robert Rossney 的答案中 JF Sebastian 的答案,以连接 NumPy 数组。
B
Boris Verkhovskiy

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

通过接受 PEP 448 引入了另一种替代方案,值得一提。

PEP 的标题为 Additional Unpacking Generalizations,在 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 必须指出:*dictionaries
这是一个很好的解决方案。但是,它不适用于列表理解。
@KevinS 这仅适用于字符串键,因为 ** 语法仅支持字符串键。
B
Boris Verkhovskiy

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

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

chain 对于两个列表来说速度较慢(但不是很多),但它是链接多个列表的最快解决方案(n > > 2)。
@cs95 比什么慢?
@Moberg 与连接列表的其他方式相比,请参阅我的基准测试here以供参考。
@cs95 您的基准测试使用 chain 对所有元素进行迭代,但会将结果转换为列表。有时这正是您想要的,但如果您只是想遍历所有元素,您可以简单地使用 chain 中的迭代器。这可能要快得多。
4
4 revs, 3 users 57%

您还可以使用 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 给我。
@Ayush 扩展方法使用 listtwo 中的值更新 listone 并返回 None。你想做: listone.extend(listtwo) 后跟 return listone
t
thefourtheye

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

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)) 可以解决问题。
c
cs95

如何在 Python 中连接两个列表?

从 3.9 开始,这些是在 python 中连接两个(或更多)列表的最流行的 stdlib 方法。

https://i.stack.imgur.com/cRqfa.png

脚注 这是一个巧妙的解决方案,因为它简洁。但是 sum 以成对的方式执行连接,这意味着这是一个二次运算,因为必须为每个步骤分配内存。如果您的列表很大,请勿使用。请参阅文档中的 chain 和 chain.from_iterable。您需要先导入 itertools。串联在内存中是线性的,因此在性能和版本兼容性方面这是最好的。 chain.from_iterable 是在 2.6 中引入的。此方法使用 Additional Unpacking Generalizations (PEP 448),但不能泛化到 N 个列表,除非您自己手动解包每个列表。 a += b 和 a.extend(b) 或多或少等效于所有实际目的。 += 在列表上调用时将在内部调用 list.__iadd__,它将第一个列表扩展第二个。

表现

2-列表连接1

https://i.stack.imgur.com/mfQTe.png

这些方法之间没有太大区别,但这是有道理的,因为它们都具有相同的复杂度(线性)。除了风格问题外,没有特别的理由偏爱其中一个。

N-List 连接

https://i.stack.imgur.com/XcX7A.png

绘图已使用 perfplot 模块生成。 Code, for your reference.

<子> 1。 iadd (+=) 和 extend 方法就地运行,因此每次测试前都必须生成一个副本。为了公平起见,所有方法都有一个可以忽略左侧列表的预复制步骤。

对其他解决方案的评论

不要以任何方式、形状或形式直接使用 DUNDER METHOD list.__add__。事实上,不要使用 dunder 方法,并按照它们的设计用途使用运算符和运算符函数。 Python 有仔细的语义,这些语义比直接调用 dunder 更复杂。这是一个例子。所以,总而言之,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 速度较慢。有关类似讨论,请参见此处。

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

从函数中产生列表元素是一种可接受的方法,但 chain 做得更快更好(它在 C 中有一个代码路径,所以它很快)。

operator.add(a, b) 是可接受的等效于 a + b 的函数。它的用例主要用于动态方法分派。否则,在我看来,更喜欢更短且更具可读性的 a + b 。 YMMV。


stackoverflow.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.”我的答案中未列出或在“评论”中批评的解决方案,我建议不要使用。
P
Peter Mortensen

这很简单,我认为它甚至显示在 the tutorial 中:

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

w
wonder.mice

这个问题直接询问加入两个列表。然而,即使您正在寻找一种加入许多列表的方法(包括加入零列表的情况),它的搜索量也相当高。

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

>>> 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 在评论中建议的替代方案也可以为您工作:

sum(a, [])

Python 3 注意:reduce 现在在 functools 中,因此您需要先导入它。
P
Peter Mortensen

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

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))
D
Dariusz Walczak

值得注意的是,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']

M
Mazdak

对于列表数量较少的情况,您可以简单地将列表添加在一起或使用就地解包(在 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]

对于具有更多列表的情况,作为更通用的方法,您可以使用 itertools 模块中的 chain.from_iterable()1 函数。另外,基于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)`。


佚名

对于 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(等效)而不是定义自己的函数。
P
Peter Mortensen

如果要以排序形式合并两个列表,可以使用 heapq 库中的 merge 函数。

from heapq import merge

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

print list(merge(a, b))

j
jpihl

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

抓住dunders通常不是最好的方法。如果 + 不在讨论范围内,请使用 operator.add
为什么加号运算符不可用?
通常它不会:) 但是如果您正在使用 map 函数进行列表连接或想要将 add 函数存储在变量中,则不能使用 +。
P
Peter Mortensen

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

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
C
Cody Gray

如果您使用的是 NumPy,您可以使用以下命令连接两个兼容维度的数组:

numpy.concatenate([a,b])

@cs95 它也不会“不要求” numpy。我应该说这实际上对我有所帮助,因为加号运算符不适用于我的应用程序
z
z33k

使用简单的列表推导:

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

它具有使用 Additional Unpacking Generalizations 的最新方法的所有优点 - 即您可以通过这种方式连接任意数量的不同迭代(例如,列表、元组、范围和生成器) - 它不限于 Python 3.5 或更高版本.


s
surya

另一种方式:

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

[*a, *b] 如何对 a + b 进行改进?
S
SuperNova
list(set(listone) | set(listtwo))

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


F
Francesco Marchetti-Stasi

正如许多人已经指出的那样,如果需要对两个列表应用完全相同的处理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循环可以处理元组变量,因此同时循环多个变量很简单。


D
Dimitris Fasarakis Hilliard

您可以使用在 list 对象上定义的 append() 方法:

mergedlist =[]
for elem in listone:
    mergedlist.append(elem)
for elem in listtwo:
    mergedlist.append(elem)

只是让你知道,如果这是你在实践中所做的,这比其他提议的方法要慢得多。见stackoverflow.com/questions/17479361/…
W
Wouter

我推荐三种连接列表的方法,但最推荐第一种方法,

# 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 循环来连接列表。所以时间复杂度远高于其他两种方法。


A
Akash Singh

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

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 代替。
F
Franz Kurt

用于连接列表的最常用方法是加号运算符和内置方法 append,例如:

list = [1,2]

list = list + [3]
# list = [1,2,3]

list.append(3) 
# list = [1,2,3]

list.append([3,4]) 
# list = [1,2,[3,4]]

在大多数情况下,这将起作用,但如果添加了列表,则 append 函数将不会扩展列表。因为这不是预期的,所以您可以使用另一种名为 extend 的方法来处理结构:

list = [1,2]
list.extend([3,4]) 
# list = [1,2,3,4]

P
Peter Mortensen

所以有两种简单的方法。

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

例子:

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)。
U
U12-Forward

您也可以只使用 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] 将按预期工作。


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

 c=a+b
 print(c)

输出:

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

在上面的代码中,“+”运算符用于将 2 个列表连接成一个列表。

另一个解决方案:

 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]

D
Dharman

我假设您想要以下两种方法之一:

保留重复元素

这很容易,只需像字符串一样连接:

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

K
Khan

提供的解决方案适用于单个列表。如果列表中有列表并且需要合并相应的列表。通过 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]]


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