Python中最快的合并两个列表的方法是什么?

33

鉴于,

list_1 = [1,2,3,4]
list_2 = [5,6,7,8]

在Python中实现以下操作,最快的方法是什么?

list = [1,2,3,4,5,6,7,8]
请注意在Python中合并两个列表有很多种方法。
我正在寻找最省时的方法。

我尝试了以下代码,以下是我的理解。

CODE

import time

c = list(range(1,10000000))
c_n = list(range(10000000, 20000000))

start = time.time()
c = c+c_n
print len(c)
print time.time() - start

c = list(range(1,10000000))
start = time.time()
for i in c_n:
    c.append(i)
print len(c)
print time.time() - start

c = list(range(1,10000000))
start = time.time()
c.extend(c_n)
print len(c)
print time.time() - start

输出

19999999
0.125061035156
19999999
1.02858018875
19999999
0.03928399086

因此,如果有人在问题中不介意重复使用list_1/list_2,则使用extend是最好的方法。另一方面,"+"是最快的方法。

但是,我不确定是否有其他选项。


3
查看此帖子 -> https://dev59.com/tnI-5IYBdhLWcg3wsKv9 - Alberto Megía
4
你在这里并不是真正的合并,而是连接... 这真的是你想要的吗?list1 = [1,2,3,5]; list2 = [4,5,6,7]应该得到什么结果? - mgilson
你无法比 list_1 + list_2 更快。 - jamylak
"extend"是合并列表的最快方法。 - F.Tamy
6个回答

34
你可以使用字符串拼接:
list = list_1 + list_2

如果您不需要保留list_1,请直接修改它:

list_1.extend(list_2)

1
@hepcat72 没什么特别的,它会产生正确的结果。 - phant0m
正确的结果是什么?如果list_1为空,而list_2包含一个字符串"a",那么list会包含[undef,"a"]还是只有["a"]? - hepcat72
3
undef?这种东西不存在。[] + ["a"] == ["a"]。如果你将一个零元素的列表和一个具有一个元素的列表相加,你最终会得到一个包含一个元素的列表,自然不是两个。 - phant0m
我是一个 Python 新手。感谢您的解释。我只是试图弄清楚 Python 的工作原理。 - hepcat72
没问题,将来你可以在Python控制台中尝试自己的示例。"试一试就知道" - phant0m
显示剩余3条评论

13

如果您正在使用Python 3,则还有另一种方法可以做到这一点,并且速度会稍微快一些(仅在Python 3.7上进行了测试)。

[*list1, *list2]

基准测试

from timeit import timeit
x = list(range(10000))
y = list(x)

def one():
    x + y

def two():
    [*x, *y]

print(timeit(one, number=1000, globals={'x':x, 'y': y}))
print(timeit(two, number=1000, globals={'x':x, 'y': y}))
0.10456193100253586
0.09631731400440913

1
有趣的是,我得到了与你相似的数字,用于具有10k元素的列表,但当我升级到具有100k元素的列表时,“one”更快(至少在使用3.6的情况下)。 - Nick stands with Ukraine
嗯,我刚试了一下有10万个元素的情况,结果第二个还是更快。 - Mohit Solanki
我使用的是3.6版本,所以可能与此有关。 - Nick stands with Ukraine
1
是的 一个:40.26142632599658 二:29.216321185995184这是100万个项目的结果,第二个明显更快。 - Mohit Solanki
1
笔记本电脑试图运行100万个项目,但已经崩溃了,我相信你的话 :) - Nick stands with Ukraine

13

我尝试了几种合并两个列表的方法(见下文),并在运行多次以规范化缓存更改后得出了以下顺序(这会导致大约15%的差异)。

import time
c = list(range(1,10000000))
c_n = list(range(10000000, 20000000))
start = time.time()
*insert method here* 
print (time.time()-start)
  • 方法1: c.extend(c_n)

    • 代表结果: 0.11861872673034668
  • 方法2: c += c_n

    • 代表结果: 0.10558319091796875
  • 方法3: c = c + c_n

    • 代表结果: 0.25804924964904785
  • 方法4: c = [*c, *c_n]

    • 代表结果: 0.22019600868225098

总结 如果要原地合并,请使用+=.extend()。它们的速度显然更快。


3
我使用Python 3.8进行了测试,并确认了Kiran的结果。请注意,方法2使用INPLACE_ADD字节码指令,这意味着它在原地(在相同的内存上)操作,因此比使用BINARY_ADD的方法3更快。 - Almenon
@Almenon 我该如何查看正在使用的字节码指令? - Jonathan
1
@Jonathan 请查看 https://docs.python.org/3/library/dis.html - Almenon

11

list_1 + list_2就可以实现。例如:

>>> list_1 = [1,2,3,4]
>>> list_2 = [5,6,7,8]
>>> list_1 + list_2
[1, 2, 3, 4, 5, 6, 7, 8]

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

0
最快的方法似乎是:
list1 + list2

benchmark.py

#!/usr/bin/env python3
import sys
from timeit import timeit

count = 1_000_000
list_size = 1_000

l1 = list(range(list_size))
l2 = list(range(list_size))


def plus():
    return l1 + l2


def plusequal():
    lst = []
    lst += l1
    lst += l2
    return lst


def asterisk():
    return [*l1, *l2]


print('#', sys.version.replace('\n', ''))
for fn in (plus, plusequal, asterisk):
    print(fn.__qualname__, timeit(fn, number=count,
                                  globals={'l1': l1, 'l2': l2}))

结果:

$ for v in 8 9 10 11; do python3.$v benchmark.py ; done
# 3.8.16 (default, Jan 19 2023, 02:07:34) [GCC 12.2.0]
plus 2.3145008360006614
plusequal 2.388007382996875
asterisk 2.4057720839991816
# 3.9.16 (main, Jan 19 2023, 02:11:50) [GCC 12.2.0]
plus 2.410123729998304
plusequal 2.810086893001426
asterisk 2.822675076997257
# 3.10.11 (main, May  7 2023, 23:10:58) [GCC 13.1.1 20230429]
plus 2.5304620300012175
plusequal 2.8561974199983524
asterisk 2.813428355999349
# 3.11.3 (main, Jun  5 2023, 09:32:32) [GCC 13.1.1 20230429]
plus 2.473347854000167
plusequal 2.8089449279978
asterisk 2.81812875399919

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