连接两个列表的最有效方法是什么list_a
,list_b
何时:
list_b
物品必须放在list_a
物品之前list_a
我有四种可能性:
# 1
list_a = list_b + list_a
# 2
for item in list_b:
list_a.insert(0, item)
# 3
for item in self.list_a:
list_b.append(item)
list_a = list_b
# 4
list_a[0:0] = list_b
Run Code Online (Sandbox Code Playgroud)
谢谢!
Lau*_*low 24
下面是一个图表,显示BigYellowCactus答案中使用的计时如何随着列表长度的增加而发展.垂直轴是在usec中初始化两个列表并将一个列表插入另一个列表前所需的时间.横轴是列表中的项目数.
鉴于
list_a = list_b + list_a
Run Code Online (Sandbox Code Playgroud)
适用于您的目的,因此您实际上并不需要list_a
对象本身来存储所有数据list_a
- 您只需要调用 它list_a
(即,您没有或不关心您拥有的任何其他变量)漂浮在那可能会引用同一个列表).
如果您也不关心它只是一个列表,但只关于它是可迭代的,那么您可以使用itertools.chain
:
list_a = itertools.chain(list_b, list_a)
Run Code Online (Sandbox Code Playgroud)
如果你确实关心某些列表事物,你可以构造一个类似于事物的类似事物chain
- 如下所示:
class ListChain(list):
def __init__(self, *lists):
self._lists = lists
def __iter__(self):
return itertools.chain.from_iterable(self._lists)
def __len__(self):
return sum(len(l) for l in self._lists)
def append(self, item):
self._lists[-1].append(item)
def extend(self, iterable):
self._lists.append(list(iterable))
def __getitem__(self, item):
for l in self._lists:
if item < len(l):
return l[item]
item -= len(l)
else:
raise IndexError
Run Code Online (Sandbox Code Playgroud)
这将需要花费很多精力(可能超过它的价值)才能在所有情况下工作 - 例如,处理切片和负面索引会浮现在脑海中.但对于非常简单的情况,这种方法可以避免大量复制列表内容.
您可以将list_b分配给切片,该切片恰好为空但位于list_a的开头:
list_a[0:0] = list_b
Run Code Online (Sandbox Code Playgroud)
这是在任何位置将列表插入另一个列表的最快方法.
小智 5
itertools.chain
只是制作了一个生成器,因此如果您可以使用生成器而不是列表,那么生成的时间是恒定的,但您在访问每个元素时要付出成本。否则list_a[0:0] = list_b
大约快 6 倍list_a = list_b + list_a
我认为这list_a = list_b + list_a
是最具可读性的选择,而且速度已经相当快了。
您提到的append()
在for
循环中使用的两种方法速度慢得无法使用,因此我没有费心将它们包含在内。
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
使用以下代码在具有 16 GB 2133 MHz LPDDR3 RAM 的 1.6 GHz 双核 Intel Core i5 上运行 Python 3.7.5 :
from timeit import timeit
import random
import matplotlib.pyplot as plt
num_data_points = 1000
step = 10
methods = [
# ordered from slowest to fastest to make the key easier to read
# """for item in list_a: list_b.append(item); list_a = list_b""",
# """for item in list_b: list_a.insert(0, item)""",
# "list_a = list(itertools.chain(list_b, list_a))",
"list_a = list_b + list_a",
"list_a[0:0] = list_b",
"list_a = itertools.chain(list_b, list_a)",
]
x = list(range(0, num_data_points * step, step))
y = [[] for _ in methods]
for i in x:
list_a = list(range(i))
list_b = list(range(i))
random.shuffle(list_a)
random.shuffle(list_b)
setup = f"list_a = {list_a}; list_b = {list_b}"
for method_index, method in enumerate(methods):
y[method_index].append(timeit(method, setup=setup, number=30))
print(i, "out of", num_data_points * step)
ax = plt.axes()
for method_index, method in enumerate(methods):
ax.plot(x, y[method_index], label=method)
ax.set(xlabel="number of elements in both lists", ylabel="time (s) (lower is better)")
ax.legend()
plt.show()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10969 次 |
最近记录: |