Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python动态数组分配,Matlab风格_Python_Arrays_Matlab_Numpy_Indexing - Fatal编程技术网

Python动态数组分配,Matlab风格

Python动态数组分配,Matlab风格,python,arrays,matlab,numpy,indexing,Python,Arrays,Matlab,Numpy,Indexing,我正在尝试将我构建的一些Matlab库迁移到python环境中。到目前为止,我面临的最大问题是基于索引规范的数组动态分配。例如,使用Matlab,键入以下内容: x = [1 2]; x(5) = 3; from numpy import * x = array([1,2]) x[4] = 3 将导致: x = [ 1 2 0 0 3] 换句话说,我之前不知道(x)的大小,也不知道它的内容。数组必须根据我提供的索引动态定义 在python中,尝试以下操作:

我正在尝试将我构建的一些Matlab库迁移到python环境中。到目前为止,我面临的最大问题是基于索引规范的数组动态分配。例如,使用Matlab,键入以下内容:

x = [1 2];
x(5) = 3;
from numpy import *
x = array([1,2])
x[4] = 3
将导致:

x = [ 1     2     0     0     3]
换句话说,我之前不知道(x)的大小,也不知道它的内容。数组必须根据我提供的索引动态定义

在python中,尝试以下操作:

x = [1 2];
x(5) = 3;
from numpy import *
x = array([1,2])
x[4] = 3
将导致以下错误:索引器错误:索引超出范围。解决方法是在循环中递增数组,然后将所需值指定为:

from numpy import *
x = array([1,2])

idx = 4
for i in range(size(x),idx+1):
    x = append(x,0)

x[idx] = 3
print x
它是可行的,但它不是很方便,而且对于n维数组可能会变得非常麻烦。我想对ndarray进行子类化以实现我的目标,但我不确定它是否可行。有人知道更好的方法吗


谢谢你的快速回复。我不知道setitem方法(我对Python相当陌生)。我简单地覆盖了ndarray类,如下所示:

import numpy as np

class marray(np.ndarray):

    def __setitem__(self, key, value):

        # Array properties
        nDim = np.ndim(self)
        dims = list(np.shape(self))

        # Requested Index
        if type(key)==int: key=key,
        nDim_rq = len(key)
        dims_rq = list(key)

        for i in range(nDim_rq): dims_rq[i]+=1        

        # Provided indices match current array number of dimensions
        if nDim_rq==nDim:

            # Define new dimensions
            newdims = []
            for iDim in range(nDim):
                v = max([dims[iDim],dims_rq[iDim]])
                newdims.append(v)

            # Resize if necessary
            if newdims != dims:
              self.resize(newdims,refcheck=False)

        return super(marray, self).__setitem__(key, value)
它就像一个符咒!但是,我需要修改上述代码,以便setitem允许根据此请求更改维度数:

a = marray([0,0])
a[3,1,0] = 0
不幸的是,当我尝试使用numpy函数时,例如

self = np.expand_dims(self,2)

返回的类型是numpy.ndarray,而不是main.marray。如果提供marray作为输入,我可以如何强制numpy函数输出marray?我认为使用array\u wrap应该是可行的,但我始终找不到确切的方法。任何帮助都将不胜感激。

冒昧地更新了我的旧答案。我想这应该能满足你的大部分需求

class matlab_list(list):
    def __init__(self):
        def zero():
            while 1:
                yield 0
        self._num_gen = zero()

    def __setitem__(self,index,value):
        if isinstance(index, int):
            self.expandfor(index)
            return super(dynamic_list,self).__setitem__(index,value)

        elif isinstance(index, slice):
            if index.stop<index.start:
                return super(dynamic_list,self).__setitem__(index,value)
            else:
                self.expandfor(index.stop if abs(index.stop)>abs(index.start) else index.start)
            return super(dynamic_list,self).__setitem__(index,value)

    def expandfor(self,index):
            rng = []
            if abs(index)>len(self)-1:
                if index<0:
                    rng = xrange(abs(index)-len(self))
                    for i in rng:
                        self.insert(0,self_num_gen.next())
                else:
                    rng = xrange(abs(index)-len(self)+1)
                    for i in rng:
                        self.append(self._num_gen.next())

# Usage
spec_list = matlab_list()
spec_list[5] = 14
class matlab\u列表(列表):
定义初始化(自):
def zero():
而1:
收益率0
self.\u num\u gen=零()
定义设置项(自身、索引、值):
如果isinstance(索引,int):
self.expandfor(索引)
返回super(动态列表,self)。\uuuuu setitem\uuuuuu(索引,值)
elif isinstance(索引、切片):
if index.stopabs(index.start)else index.start)
返回super(动态列表,self)。\uuuuu setitem\uuuuuu(索引,值)
def expandfor(自我,索引):
rng=[]
如果abs(索引)>透镜(自)-1:

如果索引这不是你想要的,但是

x = np.array([1, 2])

try:
    x[index] = value
except IndexError:
    oldsize = len(x)   # will be trickier for multidimensional arrays; you'll need to use x.shape or something and take advantage of numpy's advanced slicing ability
    x = np.resize(x, index+1) # Python uses C-style 0-based indices
    x[oldsize:index] = 0 # You could also do x[oldsize:] = 0, but that would mean you'd be assigning to the final position twice.
    x[index] = value

>>> x = np.array([1, 2])
>>> x = np.resize(x, 5)
>>> x[2:5] = 0
>>> x[4] = 3
>>> x
array([1, 2, 0, 0, 3])
由于numpy是如何在后台线性存储数据的(尽管在创建数组时可以指定它是作为行主数组还是列主数组存储),因此多维数组在这里非常棘手

>>> x = np.array([[1, 2, 3], [4, 5, 6]])
>>> np.resize(x, (6, 4))
array([[1, 2, 3, 4],
       [5, 6, 1, 2],
       [3, 4, 5, 6],
       [1, 2, 3, 4],
       [5, 6, 1, 2],
       [3, 4, 5, 6]])
您需要执行以下操作或类似操作:

>>> y = np.zeros((6, 4))
>>> y[:x.shape[0], :x.shape[1]] = x
>>> y
array([[ 1.,  2.,  3.,  0.],
       [ 4.,  5.,  6.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])

python dict将与稀疏数组一样工作。主要问题是用于初始化稀疏数组的语法将不那么漂亮:

listarray = [100,200,300]
dictarray = {0:100, 1:200, 2:300}
但在此之后,插入或检索元素的语法是相同的

dictarray[5] = 2345

您的
append
-in-loop算法需要二次时间,因此对于大型阵列,它会变得非常缓慢。请抓住这个机会,摆脱所有的临时阵列重新分配;)a) 如果您不打算使用稀疏值,也就是说,您希望按顺序设置它们,您可以使用类似于np.fromiter的东西。b) 如果您仍然打算使用子类ndarray,本文应该澄清为什么不保留该类型以及如何修复它。不幸的是,这在n维中不起作用,并且可能不如数组有效。