python - 将 'array of objects' 与 'object of arrays' 的功能相结合

标签 python algorithm oop numpy

我正在寻找某种范例或实现来有效地处理多组耦合的 N 维数组(ndarray)。具体来说,我希望有一个实现,允许我对整个对象的数组进行切片(例如 someObjs = objects[100:200]),或这些对象的单个属性(例如 somePars1 =objects.par1[100:200]) --- 同时。

为了扩展上面的示例,我可以通过两种方式构造以下子集:

def subset1(objects, beg, end):
    pars1 = [ obj.par1 for obj in objects[beg:end] ]
    pars2 = [ obj.par2 for obj in objects[beg:end] ]
    return pars1, pars2

def subset2(objects, beg, end):
    pars1 = objects.par1[beg:end]
    pars2 = objects.par2[beg:end]
    return pars1, pars2

而且它们是相同的。


编辑:

一种方法是重写 __getitem__ (等)方法,例如,

class Objects(object):
    def __init__(self, p1, p2):
        self.par1 = p1
        self.par2 = p2
    ...
    def __getitem__(self, key):
        return Objects(self.p1[key], self.p2[key])

但这效率极低,而且会重复子集。也许有办法返回子集的 View ??

最佳答案

对象数组和使用数组方法的对象

示例对象类

In [56]: class MyObj(object):
   ....:     def __init__(self, par1,par2):
   ....:         self.par1=par1
   ....:         self.par2=par2

这些对象的数组 - 只不过是带有数组包装器的列表

In [57]: objects=np.array([MyObj(1,2),MyObj(3,4),MyObj(2,3),MyObj(10,11)])
In [58]: objects
Out[58]: 
array([<__main__.MyObj object at 0xb31b196c>,
       <__main__.MyObj object at 0xb31b116c>,
       <__main__.MyObj object at 0xb31b13cc>,
       <__main__.MyObj object at 0xb31b130c>], dtype=object)

“子集”选择类型:

In [59]: [obj.par1 for obj in objects[1:-1]]
Out[59]: [3, 2]

可以包含此类数组的另一个类。这比定义数组子类更简单:

In [60]: class MyObjs(object):
   ....:     def __init__(self,anArray):
   ....:         self.data=anArray
   ....:     def par1(self):
   ....:         return [obj.par1 for obj in self.data]

In [61]: Obs = MyObjs(objects)
In [62]: Obs.par1()
Out[62]: [1, 3, 2, 10]

subset2 选择类型:

In [63]: Obs.par1()[1:-1]
Out[63]: [3, 2]

目前 par1 是一个方法,但可以创建一个属性,允许 Obs.par1[1:-1] 语法。

如果 par1 返回数组而不是列表,索引会更强大。

如果MyObjs有一个__getitem__方法,那么它可以被索引

Obs[1:-1]

该方法可以通过多种方式定义,但最简单的是将索引“切片”应用于“数据”:

def __getitem__(self, *args):
    # not tested
    return MyObjs(self.data.__getitem(*args))

我只关注语法,而不是效率。一般来说,一般对象的 numpy 数组不是很快或很强大。这样的数组基本上是指向对象的指针列表。

结构化数组和重新数组版本

另一种可能是np.recarray。另一位发帖者只是询问他们的名字。它们本质上是结构化数组,其中字段可以作为属性进行访问。

使用结构化数组定义:

In [64]: dt = np.dtype([('par1', int), ('par2', int)])
In [66]: Obj1 = np.array([(1,2),(3,4),(2,3),(10,11)], dtype=dt)
In [67]: Obj1
Out[67]: 
array([(1, 2), (3, 4), (2, 3), (10, 11)], 
      dtype=[('par1', '<i4'), ('par2', '<i4')])
In [68]: Obj1['par1'][1:-1]
Out[68]: array([3, 2])
In [69]: Obj1[1:-1]['par1']
Out[69]: array([3, 2])

或作为重新排列

In [79]: Objrec=np.rec.fromrecords(Obj1,dtype=dt)
In [80]: Objrec.par1
Out[80]: array([ 1,  3,  2, 10])
In [81]: Objrec.par1[1:-1]
Out[81]: array([3, 2])
In [82]: Objrec[1:-1].par1
Out[82]: array([3, 2])

关于python - 将 'array of objects' 与 'object of arrays' 的功能相结合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32831839/

相关文章:

python - 比较列表并根据两者的内容创建新列表

c# - 用于确定特定范围内有多少元素的数据结构?

algorithm - 插入等值元素

java - 单根层次结构使垃圾收集器的实现变得更加容易

python - 可以在不使用括号的情况下调用单参数 Python 函数吗?

python - 在pandas中加入2个具有不同列名的数据框

python - 嵌套字典的子集

c++ - 将 std::unique_ptr 移动到 std::vector 内的新位置

matlab - 我在初始化 MATLAB 类时遇到问题

oop - DDD - 应如何设计域规则,以便上层知道规则何时被破坏?