I need to obtain a list (cell array) of the contents of a single subfield in a PDB file. I have prepared my structure and am now looking for something like
resnames = getfield(PS.Model.Atom,'resName')
This however only leaves me with the first entry. I need an output similar to the what command.
I believe you may have something like this:
a{1}='s';
a{2}='t';
Now calling it like so
a{:}
will return several times:
ans =
s
ans =
t
However, if you can wrap it with brackets:
{a{:}}
It will nicely return everything at once:
ans =
's' 't'
Now ans is a cell array.
I have been unable to guess your exact structure, but hopefully this solution (wrapping stuff with brackets) still works. If not, you can always just loop through your variable and extract the elements one by one.
Your struct array is not scalar at some point in the tree. Somewhere in the hierarchy you have 1xN struct array, which would give you multiple ans outputs like that. Another suggestion is to use dynamic field names. Instead of getfield, this would be:
PS.Model.Atom.('resName')
Thus, you could take Dennis' suggestion and form a cell of all stings like:
resnames = {PS.Model.Atom.('resName')};
Related
I have looked for the proper way to access a given field of a struct and the manual and online searches didn't help.
Formally, let MyStruct be a 1xn struct variable. It's easy to list all the elements stored in a field with:
MyStruct.Thisfield
ans =
0.7010
ans =
0.310
ans =
0.444
etc.
Now the only way I found to be able to access an element of this is to use a temporary variable, e.g. temp={MyStruct.Thisfield} and then temp{1,2} etc. I think it's clumsy but can't figure out what else to do.
This:
>> MyStruct{1,1}.Thisfield
Cell contents reference from a non-cell array object.
and this:
>> MyStruct.Thisfield{1,1}
Field reference for multiple structure elements that is followed by
more reference blocks is an error.
are my unsuccessful attempts.
See an example in situ in this answer of mine https://stackoverflow.com/a/22813577/2777181
If you currently do:
temp={MyStruct.Thisfield}
temp{1,2}
You can replace this by directly accessing the second element of the struct (As also mentioned by #Jucestain):
MyStruct(2).Thisfield
Note that in one dimensional calls, you don't need to specify all dimensions. So in your original code you could have done
temp{2}
I have implemented a binary tree in Matlab using 'struct' type elements as nodes. An N-node tree has, say, N such structs.
My problem is that I have M such trees, each having a different number of nodes, N_1, N_2, ..., N_M. How can I hold these trees in a list or array which can be iterated? Several trials like struct of structs did not seem to work.
Edit: I want to do something like the following. myClassTree returns a tree with N_i nodes.
trees = struct;
for i=1:nTrees
tree = myClassTree(train(bags(i,:),:), entropy, depth);
trees(i) = tree;
end
The easiest thing is to create a cell array. Simply replace trees(i) = tree; with trees{i} = tree; (note braces, rather than parenthesis).
Cell arrays are useful whenever you want to store an array of mixed data types. To access elements of a cell array, you can use the braces again. For example, this should work as you expect:
currentTree = trees{someIndex};
The code that you posted creates an array of structs, which only works if the structures have the same fieldnames.
If you wanted (not recommended) you could created a struct of structs, but doing somehting like this trees.(['n' sprintf('%04d',i)]) = tree;. (But please don't.)
The "s{1} annoyance" of the title refers to the first line within the for-block below:
for s = some_cell_array
s = s{1}; % unpeel the enclosing cell
% do stuff with s
end
This s = s{1} business is necessary because the iteration over some_cell_array does not really iterate over the contents of some_cell_array, but rather over 1-element cells, each containing an item from some_cell_array.
Putting aside the question of who could possibly want this behavior as the default, is there any way to iterate over the bare contents of some_cell_array?
I don't think there is a way to avoid this problem in the general case. But there is a way if your cell array has all numbers or all chars. You can convert to an array and let the for loop iterate over that.
For example, this:
some_cell_array = {1,2,3}
for s = [some_cell_array{:}] % convert to array
s
end
Gives:
s =
1
s =
2
s =
3
Another option is to create a function that operates on every cell of the array. Then you can simply call cellfun and not have a loop at all.
I don't have any ideas about who would want this behavior or how it could be useful. My guess as to why it works this way, however, is that it's an implementation thing. This way the loop iterator doesn't change type on different iterations. It is a cell every time, even if the contents of that cell are different types.
Just a small add-on to Sam Robert's comment to the original question, on why you should prefer s{:} over s{1} : easier bug tracking.
Imagine you mistakenly stored your cell s as a column instead of a line. Then
for s = some_cell_array
will simply return a cell s which is equal to some_cell_array. Then the syntax s{1} will return the first element of some_cell_array, whereas s{:} will produce a list of all elements in some_cell_array. This second case will much more surely lead to an execution error in the following code. Whereas the first case could sometimes create a hard bug to detect.
I have a struct array called AnalysisResults, that may contain any MATLAB datatypes, including other struct arrays and cell arrays.
Then I have a string called IndexString, which is the index to a specific subfield of StructArray, and it may contain several indices to different struct arrays and cell arrays, for example:
'SubjectData(5).fmriSessions{2}.Stats' or 'SubjectData(14).TestResults.Test1.Factor{4}.Subfactor{3}'.
And then I have a variable called DataToBeEntered, which can be of any MATLAB datatype, usually some kind of struct array, cell array or matrix.
Using eval, it is easy to enter the data to the field or cell indexed by IndexString:
eval([ 'AnalysisResults.', IndexString, ' = DataToBeEntered;' ])
But is it possible to avoid using eval in this? setfield doesn't work for this.
Thank you :)
Well, eval surely is the easiest way, but also the dirtiest.
The "right" way to do so, I guess, would be to use subsasgn. You will have to parse the partial MATLAB command (e.g. SubjectData(5).fmriSessions{2}.Stats) into the proper representation for those functions. Part of the work can be done by substruct, but that is the lightest part.
So for example, SubjectData(5).fmriSessions{2}.Stats would need to be translated into
indexes = {'.' , 'SubjectData',
'()', {5},
'.' , 'fmriSessions',
'{}', {2},
'.' , 'Stats'};
indexStruct = substruct(indexes{:});
AnalysisResult = subsasgn(AnalysisResult, indexStruct, DataToBeEntered);
Where you have to develop the code such that the cell array indexes is made as above. It shouldn't be that hard, but it isn't trivial either. Last year I ported some eval-heavy code with similar purpose and it seemed easy, but it is quite hard to get everything exactly right.
You can use dynamic field names:
someStruct.(someField) = DataToBeEntered;
where someField is a variable holding the field name, but you will have to parse your IndexString to single field name and indices.
I have a function that takes a variable number of inputs, say myfun(x1,x2,x3,...).
Now if I have the inputs stored in a structure array S, I want to do something like
myfun(S.x1,S.x2,...). How do I do this?
You can first convert your structure to a cell array using STRUCT2CELL, and then use that to generate the list of multiple inputs.
S = struct('x1','something','x2','something else');
C = struct2cell(S);
myfun(C{:});
Note that the order in which the fields in S are defined are the order in which the inputs are passed. To check that the fields are in the proper order, you can run fieldnames on S, which returns a cell with field names corresponding to the values in C.
Something to add to Jonas' answer: Actually you can omit the struct and go right for the cell which is then expanded into a list for the function arguments:
c = {125, 3};
nthroot(c{:})