填充数组的最快方法?
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)
我想像这样填充一个大小为 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)