如何在Python中像指针一样高效地迭代数组

How to iterate an array in Python pointer-likely and efficiently?

本文关键字:一样 高效 数组 迭代 Python 指针      更新时间:2023-10-16

我是Python的新手,我想迭代一个数组来计算基于前一个元素的下一个元素。我可以用c++的方式来考虑这一点,但如何在Python中使用Numpy或Pandas来实现这一点?我知道类似的方法是使用移位,但这种方法似乎不是很有效。

下面是一个简单的斐波那契数列例子:

int arr[10];
arr[0] = 1;
arr[1] = 1;
int* pt = &arr[2];         <--get a iterator like a moving pointer
int count = 8;
while (count > 0)
{
    *pt = pt[-1] + pt[-2]; <--access previous k element based on current index
    count--;
    pt++;                  <--point to next element
}
for (int i = 0; i < 10; i++)
    cout << arr[i] << endl;

列表:

L = [1, 1]
while len(L) != 10:
    L.append(L[-1] + L[-2]) <--But I have to append element every time
print L

你的c++的直接numpy模仿是

arr=np.ones((10,))
for i in range(2,arr.shape[0]):
     arr[i]=arr[i-1]+arr[i-2]
生产:

array([  1.,   1.,   2.,   3.,   5.,   8.,  13.,  21.,  34.,  55.])

这可能不是numpy中最有效的方法,但这是讨论的开始。

大多数快速的numpy操作使用编译的c代码,并且结果是缓冲的,因此执行快速的顺序操作是棘手的。最好将numpy操作视为并行操作,同时处理数组的所有项(不优先考虑顺序)。例外是ufunccumsumcumprod——累积进程,以及一个称为at的未缓冲的ufunc。我得试一试,看看有没有办法用这些工具来计算这个级数。

另一种选择是在C或c++中实现计算并链接它。cython是最方便的工具。


http://wiki.scipy.org/Cookbook/Ctypes head-6a582bd7b101bca0df6e5631a06e2d1d76e35a95是一个使用ctypesc代码与numpy一起计算斐波那契的例子。

http://numpy-discussion.10968.n7.nabble.com/vectorizing-recursive-sequences-td35532.html描述了计算这个级数的一种简便方法。它取决于ufunc接受out数组。作者承认,这也取决于实现细节,特别是计算没有缓冲。

arr=np.ones((10,))
np.add(arr[:-2], arr[1:-1], out=arr[2:])

前2个参数的元素被逐个添加,并存储在out数组中。

arr[2:] = arr[:-2]+arr[1:-1]

不能工作,因为有缓冲


http://docs.cython.org/src/tutorial/cython_tutorial.html fibonacci-fun

是fibonacci的一个Cython示例。它应该很快,但它只是打印结果,而不是将它们累加到一个数组中。但是,在Cython/c版本中,将结果存储在Cython数组或memoryview中应该不难。

这是一个cython脚本,可以保存为pyx,编译和导入。它可以被改进为有用性和速度,但它足以测试这个概念:

import numpy as np
narr = np.ones((10,), dtype=np.dtype("i"))
cdef int [:] narr_view = narr
cpdef void fib(int[:] arr):
    I = arr.shape[0]
    for i in range(2,I):
        arr[i] = arr[i-2]+arr[i-1]
fib(narr_view)
print 'fib arr:', narr