【问题标题】:Efficient 2d list initialization [python]高效的二维列表初始化 [python]
【发布时间】:2020-05-21 13:38:41
【问题描述】:

我正在为图的邻接矩阵编写代码并发现这个问题:

Best and/or fastest way to create lists in python

所以,我只是写了这个来初始化我的邻接矩阵,因为它似乎是迄今为止初始化列表的最快方法。

import time
t1 = time.time()
matrix = [[0]*5000]*5000
t2 = time.time()

t2-t1

0.0

但是在做了一些操作之后,我意识到每次更改/附加一个元素时,效果都会应用于所有子列表,这意味着每个列表只是一个参考,即使它在真实场景中也不起作用快。

我不能使用numpy,因为算法网站不允许使用外部模块/库。我认为numpy 将是一般场景的理想解决方案。

现在,显然大多数其他 2d/multi-dim 列表初始化答案都建议列表理解,

import time
t1 = time.time()
matrix = [[0 for i in range(5000)] for j in range(5000)]
t2 = time.time()
print(t2-t1)

0.7021145820617676

但是,考虑到在算法站点中解决图形问题的严格时间限制,它似乎很慢(与其他语言相比)。

有没有更快的方法在 python 中初始化 2d/3d 列表?

如果有重复,请告诉我,到目前为止,我没有找到任何显示多维列表初始化方法之间时间比较的东西。

【问题讨论】:

  • 如何更改列表中的元素?我想当你追加时,没有问题,因为它只是将该元素追加到当前列表中。
  • 实际上并不是,第一个代码 sn-p 中的 append 也不起作用。如果我将 54 附加到第 0 个子列表,则所有子列表看起来都像 [0, 54]。
  • 我意识到的原因是 * 操作会复制多个引用,它实际上并没有创建任何带有数字的列表(在这种情况下为 0)。
  • "它看起来很慢(与其他语言相比)" 欢迎使用 Python。你还有其他限制吗?你可以使用 PyPy、Cython、Numba 吗?你真的需要一个邻接 matrix,还是一个邻接 list (Dict[Node, [List[Node]]]) 也可以?
  • 谢谢,@MisterMiyagi。我知道我可以使用 cython/numba/numpy 等进行优化,但它们在算法站点中是不允许的。是的,我绝对可以在大多数算法中使用邻接列表,但有时我更喜欢邻接矩阵,因为它会导致代码更短。因此,这是一个一般性的询问,以了解是否有什么我没有做但可以做的事情来提高相同设置中的速度(没有额外的模块,邻接矩阵)。

标签: python-3.x list multidimensional-array


【解决方案1】:

问题来自第二级列表。 [0] * 5000 很好,因为它构建了一个不可变值的列表。因此,如果您更改该列表中的值,您实际上将替换它。但是由于列表是可变的,您不能使用该方法来构建列表列表。

但是这个:

[[0] * 5000 for i in range(5000)]

仍然是正确的。它构建了 5000 个不同的(不可变的)数字列表,因此它允许您更改任何单个元素而不会产生不必要的副作用。而且它比您当前的代码效率更高。

【讨论】:

  • 谢谢,这消除了我的许多困惑。就速度而言,我想这是我能做到的最好的了。
【解决方案2】:

我找到了一种比做你的理解列表更快的方法,但仍然比做matrix=[[0]*5000]*5000 慢得多。我不是专家,但我怀疑您的方法是如此之快,因为它并没有真正创建大小为 5000x5000 的列表,而是创建大小为 5000 的列表并重复它,正如您所注意到的。

您的方法在我的计算机中需要 2.098e-5 秒。我的方法在我的计算机中需要 0.1236 秒(我的方法在您的计算机中可能需要更长的时间,因此它可能会更慢)。

mat = []
[mat.append([0]*5000) for i in range(5000)]

你可以试试,也许它可以缓解你的问题。

【讨论】:

  • 我希望始终如一地追加到一个列表比使用理解构建相同的列表效率低。您是否尝试使用timeit 对两种方式进行基准测试?
  • mat = [[0] * 5000 for i in range(5000)] 的时间差异很小(差异小于 5%)。不过,直接使用的列表推导的可读性要好得多。习惯上,for 循环比列表推导更可取,以触发副作用。
猜你喜欢
  • 1970-01-01
  • 2022-07-22
  • 2013-11-21
  • 2011-09-08
  • 1970-01-01
  • 2018-04-15
  • 2012-04-14
  • 2016-05-10
  • 1970-01-01
相关资源
最近更新 更多