I've often seen the following conversion approaches:
matlab array -> python numpy array
matlab cell array -> python list
matlab structure -> python dict
So in your case that would correspond to a python list containing dicts, which themselves contain numpy arrays as entries
item[i]['attribute1'][2,j]
Note
Don't forget the 0-indexing in python!
[Update]
Additional: Use of classes
Further to the simple conversion given above, you could also define a dummy class, e.g.
class structtype():
pass
This allows the following type of usage:
>> s1 = structtype()
>> print s1.a
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-40-7734865fddd4> in <module>()
----> 1 print s1.a
AttributeError: structtype instance has no attribute 'a'
>> s1.a=10
>> print s1.a
10
Your example in this case becomes, e.g.
>> item = [ structtype() for i in range(10)]
>> item[9].a = numpy.array([1,2,3])
>> item[9].a[1]
2
A simple version of the answer by @dbouz , using the idea by @jmetz
class structtype():
def __init__(self,**kwargs):
self.Set(**kwargs)
def Set(self,**kwargs):
self.__dict__.update(kwargs)
def SetAttr(self,lab,val):
self.__dict__[lab] = val
then you can do
myst = structtype(a=1,b=2,c=3)
or
myst = structtype()
myst.Set(a=1,b=2,c=3)
and still do
myst.d = 4 # here, myst.a=1, myst.b=2, myst.c=3, myst.d=4
or even
myst = structtype(a=1,b=2,c=3)
lab = 'a'
myst.SetAttr(lab,10) # a=10,b=2,c=3 ... equivalent to myst.(lab)=10 in MATLAB
and you get exactly what you'd expect in matlab for myst=struct('a',1,'b',2,'c',3).
The equivalent of a cell of structs would be a list of structtype
mystarr = [ structtype(a=1,b=2) for n in range(10) ]
which would give you
mystarr[0].a # == 1
mystarr[0].b # == 2
Assuming that the structure contains fields with scalar numeric values, you can use this struct2array based approach -
search_num = 6; %// Edit this for a different search number
fns=fieldnames(Columns) %// Get field names
out = fns(struct2array(Columns)==search_num) %// Logically index into names to find
%// the one that matches our search
Goal:
Construct two vectors from your struct, one for the names of fields and the other for their respective values. This has analogy to the dict in Python or map in C++, where you have unique keys being mapped to possibly non-unique values.
Simple Solution:
You can do this very simply using the various functions defined for struct in Matlab, namely: struc2cell() and cell2mat()
For the particular element of interest, say
1of your structColumns, get the names of all fields in the form of a cell array, usingfieldnames()function:fields = fieldnames( Columns(1) )Similarly, get the values of all the fields of that element of
Columns, in the form of a matrixvals = cell2mat( struct2cell( Columns(1) ) )Next, find the field with the corresponding value, say 6 here, using the
findfunction and convert the resulting 1x1 cell into a char usingcell2mat()function :cell2mat( fields( find( vals == 6 ) ) )which will yield:
T21
Now, you can define a function that does this for you, e.g.:
function fieldname = getFieldForValue( myStruct, value)
Advanced Solution using Map Container Data Abstraction:
You can also choose to define an object of the containers.map class using the field-names of your struct as the keySet and values as valueSet.
myMap = containers.Map( fieldnames( Columns(1) ), struct2cell( Columns(1) ) );
This allows you to get keys and values using corresponding built-in functions:
myMapKeys = keys(myMap);
myMapValues = values(myMap);
Now, you can find all the keys corresponding to a particular value, say 6 in this case:
cell2mat( myMapKeys( find( myMapValues == 6) )' )
which again yields:
T21
Caution: This method, or for that matter all methods for doing so, will only work if all the fields have the values of the same type, because the matrix to which we are converting vals to, need to have a uniform type for all its elements. But I assume from your example that this would always be the case.
Customized function/ logic:
struct consists of elements that contain fields which have values, all in that order. An element is thus a key for which field is a value. The essence of "lookup" is to find values (which are non-unique) for specific keys (which are unique). Thus, Matlab has a built-in way of doing so. But what you want is the other way around, i.e. to find keys for specific values. Since its not a typical use case, you need to write up your own logic or function for it.
If the contents are scalars: convert from struct to cell, and then from cell to matrix:
mean(cell2mat(squeeze(struct2cell(A))), 2)
The simplest solution I know
F=fieldnames(A)
G=struct()
for ix=1:numel(F)
G.(F{ix})=mean([A.(F{ix})]);
end
I came across another idea to solve this:
cell2struct(cellfun(@(x)(mean([A.(x)])),fieldnames(A),'uni',false),fieldnames(A),1)
If a vector and not a struct is the intended output, remove the outer cell2struct
If you're on 3.3 and up, there's types.SimpleNamespace. Other than that, an empty class is probably your best option.
The simplest and intuitively most similar Python implementation would be to use type to instantiate a temporary class. It is practically similar to making a dummy class, but I think it semantically expresses the intent of a struct--like object more clearly.
>>> s = type('', (), {})()
>>> s.a = 4
>>> s.a
4
Here, type is used to create a nameless class (hence the '') with no bases (or parent classes, indicated by the empty tuple) and no default class attributes (the empty dictionary) and the final () instantiates the class/struct. Bear in mind that values passed to the dictionary do not show up in the instance's __dict__ attribute, but this fact may not be relevant to you. This method also works in older versions (< 3.x) of Python.