snowleopard
snowleopard

Reputation: 739

Accessing numpy array based on attribute of object

I have a numpy array that contains a list of objects.

x = np.array([obj1,obj2,obj3])

Here is the definition of the object:

class obj():
    def __init__(self,id):
        self.id = id

obj1 = obj(6)
obj2 = obj(4)
obj3 = obj(2)

Instead of accessing the numpy array based on the position of the object, i want to access it based on the value of id.

For example:

# x[2] = obj3
# x[4] = obj2
# x[6] = obj1

After doing some research, I learned that i could make a structured array:

x = np.array([(3,2,1)],dtype=[('2', 'i4'),('4', 'i4'), ('6', 'i4')])

# x['2'] --> 3

However, the problem with this is that i want the array to take integers as indexes, and dtypes must have a name of type str. Furthermore, i don't think structured arrays can be lists of objects.

Upvotes: 3

Views: 1324

Answers (2)

Holt
Holt

Reputation: 37616

If you only want to be able to access subarrays "by-index" (e.g. x[2, 4]), with index as id, then you could simply create your own struct:

import collections    

class MyArray (collections.OrderedDict):
    def __init__ (self, values):
        super(MyArray, self).__init__ ((v.id, v) for v in values)
    def __rawgetitem (self, key):
        return super (MyArray, self).__getitem__ (key)
    def __getitem__ (self, key):
        if not hasattr (key, '__iter__'):
            key = (key, )
        return MyArray (self.__rawgetitem (k) for k in key)
    def __repr__ (self):
        return 'MyArray({})'.format(', '.join('{}: {}'.format(k, self.__rawgetitem(k)) for k in self.keys()))
>>> class obj():
...     def __init__(self,id):
...         self.id = id
...     def __repr__ (self):
...         return "obj({})".format(self.id)
...
>>> obj1 = obj(6)
>>> obj2 = obj(4)
>>> obj3 = obj(2)
>>> x = MyArray([obj1, obj2, obj3])
>>> x
MyArray({2: obj(2), 4: obj(4), 6: obj(6)})
>>> x[4]
obj(4) 
>>> x[2, 4]
MyArray({2: obj(2), 4: obj(4)})

Upvotes: 1

jbndlr
jbndlr

Reputation: 5210

You should be able to use filter() here, along with a lambda expression:

np.array(filter(lambda o: o.id == 1, x))

However, as filter() returns a list (in Python 3+, it should return an iterator), you may want to generate a new np.array from the result.

But this does not take care of duplicate keys, if you want to access your data key-like. It is possible to have more than one object with the same id attribute. You might want to control uniqueness of keys.

Upvotes: 3

Related Questions