我已经做了很多事情,要求我使用list
.append()
函数,以及numpy.append()
函数用于numpy数组。我注意到,当数组的大小很大时,两者都会变得非常慢。
我需要一个动态增长的数组,大小约为100万个元素。我可以自己实现这个,就像std::vector
是用C ++编写的那样,通过添加无法从外部访问的缓冲区长度(保留长度)。但我必须重新发明轮子吗?我想它应该在某个地方实现。所以我的问题是:Python中是否存在这样的事情?
我的意思是: Python中是否存在能够在大多数情况下以O(C)
的时间复杂度动态增长的数组类型?
答案 0 :(得分:1)
两者都使用底层数组。相反,您可以使用collections.deque
来专门添加和删除两端的元素,其中O(1)复杂度
答案 1 :(得分:0)
numpy数组的内存在其文档中有详细描述,并在此处进行了大量讨论。列表内存布局也已经讨论过,但通常只与numpy形成鲜明对比。
numpy数组具有固定大小的数据缓冲区。 “增长”它需要创建一个新阵列,并将数据复制到它。 np.concatenate
在编译代码中执行此操作。 np.append
以及所有stack
函数都使用concatenate
。
根据我的理解,列表包含一个连续的数据缓冲区,其中包含指向其他对象的指针。 Python在该缓冲区中维护了一些自由空间,因此list.append
的添加相对快速而简单。但是当自由空间填满时,它必须创建一个新的缓冲区和复制指针。我可以看到大型列表可能会变得昂贵的地方。
因此,列表将存储每个元素的指针,以及内存中其他位置的元素本身(例如浮点数)。相比之下,浮点数组将浮点数本身存储为缓冲区中的连续字节。 (对象dtype数组更像列表)。
迭代创建数组的推荐方法是使用append
构建列表,并在结尾创建一次数组。重复的np.append
或np.concatenate
相对较贵。
deque
。我不太了解它如何存储数据。文档说它可以在开始时添加元素,就像最后一样容易,但随机访问比列表慢。这意味着它将数据存储在某种链接列表中,因此查找nth
元素需要在其之前遍历n-1
链接。因此,在增长缓解和访问速度之间存在折衷。
将元素添加到列表的开头需要创建一个新的指针列表,并在开头添加新的指针。因此,从常规列表的开头添加和删除元素比在最后执行此操作要昂贵得多。
推荐软件不属于SO的核心目的。其他人可能会提出建议,但如果关闭则不要感到惊讶。
像HDF5
这样的文件格式是专为大型数据集设计的。它们通过“分块”等功能适应增长。并且有各种各样的数据库包。