【发布时间】:2021-04-15 01:35:02
【问题描述】:
我有一个大型 NumPy 数组 nodes = np.arange(100_000_000),我需要通过以下方式重新排列这个数组:
- 记录然后删除数组中的中间值
- 将数组拆分为
left一半和right一半 - 对每一半重复步骤 1-2
- 当所有值都用完时停止
因此,对于较小的输入示例nodes = np.arange(10),输出将是:
[5 2 8 1 4 7 9 0 3 6]
这是天真的做的:
import numpy as np
def split(node, out):
mid = len(node) // 2
out.append(node[mid])
return node[:mid], node[mid+1:]
def reorder(a):
nodes = [a.tolist()]
out = []
while nodes:
tmp = []
for node in nodes:
for n in split(node, out):
if n:
tmp.append(n)
nodes = tmp
return np.array(out)
if __name__ == "__main__":
nodes = np.arange(10)
print(reorder(nodes))
但是,这对于 nodes = np.arange(100_000_000) 来说太慢了,所以我正在寻找一个更快的解决方案。
【问题讨论】:
-
太慢有多慢?即现在有多快,你需要多快?
-
我认为任何小于 2 秒(最好小于 1 秒)的时间都可以。
-
输入数组中的数字是否总是像从 arange 一样按顺序开始,还是可以是任意的数字组合?也可以有重复吗?
-
是的,订单总是从
0到n-1,如arange。没有重复。 -
我更新了我的答案并投票给了另一个答案,我认为这可能是你摆脱 numpy 的最佳选择(使用相同的算法,Cython 或 C/C++ 或 rust 会更快)。您会看到我在对该答案的评论中指出,由于 a 中的每个值都只是该值的索引,因此无需实际创建该数组,因此答案仅取决于其大小。
标签: python performance numpy