填充数组的最快方法?

Fastest way to populate an array?

我想像这样填充一个大小为 n 的数组(一个非常大的数组):

1 for i = 1, (n/2)+1
2 for i = 2, 3, ... , (n/2)
0 for i = (n/2)+2, ... , n

从 0 迭代到 n 并为每个语句使用 if 语句和 % 是最快的方法吗?

像这样:

array = []
for index in range(1,n):
    if index == 1 or (index % ((n/2)+1) == 0):
        array.append(1)
    if index == 2 or index == 3 or (index % (n/2) == 0):
        array.append(2)
    if (index % ((n/2)+2) == 0):
        array.append(0)

我试过想其他方法来做到这一点,但我没有想出任何办法。我不是职业程序员,但我不确定我还能如何实现它。

您可能需要为此使用 numpy。您可以使用 np.r_ 连接多个切片并使用它们切片分配数组:

import numpy as np

n = 10
a = np.zeros(n)
a[np.r_[0,n//2]] = 1
a[np.r_[1:n//2]] = 2
a[np.r_[n//2+1:n]] = 0

print(a)
array([1., 2., 2., 2., 2., 1., 0., 0., 0., 0.])

由于其他答案与 numpy 数组一起使用,速度非常快,我想添加一些其他答案以确保完整性。 (关于如果 n 是奇数该怎么办以及作者是否期望 zero-based 或 one-based 索引的原始问题显然存在一些歧义。)

您可以使用列表推导式非常简单地创建列表

[1 if i in [0, n/2] else (2 if i <=(n/2) else 0) for i in range(0, n)]

但是通过扩展 class:

来扩展列表的功能会更快
class NewThing(list):
    def __init__(self, n):
        self.n = n
    def __getitem__(self,i):
        if i in {0,n/2}:
            return 1
        elif i <=n/2:
            return 2
        return 0
    def to_list(self):
        return [self[i] for i in range(0, n)]

>>>unique_list = NewThing(len(u))
>>>unique_list[4]
2
>>>unique_list.to_list()
[1, 2, 2, 2, 2, 1, 0, 0, 0, 0]

您可以调用整个列表,也可以只调用单个元素。创建整个列表仍然很慢。

构造此类集合的最有效方法是使用 numpy 数组。

我们可以这样构造:

import numpy as np

def generate_array(n):
    a = np.hstack((np.full(n//2+1, 2), np.zeros(n//2-1)))
    a[[0, n//2]] = 1
    return a

例如:

>>> generate_array(6)
array([1., 2., 2., 1., 0., 0.])
>>> generate_array(10)
array([1., 2., 2., 2., 2., 1., 0., 0., 0., 0.])
>>> generate_array(16)
array([1., 2., 2., 2., 2., 2., 2., 2., 1., 0., 0., 0., 0., 0., 0., 0.])

时间:

对于 n=100_000,我们得到:

>>> timeit(partial(generate_array, 100_000), number=10_000)
1.0764452270013862

对于 n=1_000_000,我们得到:

>>> timeit(partial(generate_array, 1_000_000), number=1_000)
6.448311180000019

生成一个包含 100k 个元素的数组,因此大约需要(包括 partial 的小开销等)107.64 µs,生成一个包含 1M 个元素的数组需要 6448.31µs.

偶数 n:

def generate_array2(n):
    a = np.empty((2,n//2))
    a[0]=2
    a[1]=0
    a[:,0]=1
    return a.ravel()

%timeit a= generate_array2(1_000_000)
491 ± 6.58 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)