Clear Filters
Clear Filters

Access to array of structs (no for loops)

42 views (last 30 days)
Dear All,
From an array of structs I want to access all last elements of field datarow using one command.
Construct the array of structs:
%init struct
rec.datarow = [1,2,3,4,5];
rec.datacol = [1,2,3,4,5]'; = 'apple';
%init array of structs
rec(2:3) = rec;
Access fields name, datarow, datacol and last element of datarow of first struct. No problem here.
%get field name of all structs in once using comma-separated lists
allnames = {}
%get field datarow of all structs in once using comma-separated lists
alldatarow = [rec.datarow]
%get field datacol of all structs in once using comma-separated lists
alldatacol = [rec.datacol]
%get end value of field datarow of first struct
v1 = rec(1).datarow(end)
It appear to be sensible to store data in column format because the collection in comma separated lists yields in a handy matrix.
Now my question: Is there a way to access all end values of datarow with one command (no for loops or temporary variables)?
I was expecting that the following command should work:
%but how to get the end values of datarow of all structs in once??
allendvalues = [rec.datarow(end)]
But I get this error: Expected one output from a curly brace or dot indexing expression, but there were 3 results
Anyone some ideas?

Accepted Answer

Stephen23 on 5 May 2019
Edited: Stephen23 on 5 May 2019
"Is there a way to access all end values of datarow with one command (no for loops or temporary variables)?"
"Anyone some ideas?"
You could hide the loop inside a cellfun or an arrayfun call (but an explicit loop is usually more efficient):
>> arrayfun(@(s)s.datarow(end),rec)
ans =
5 5 5
The cause of that error message is explained here:
You can learn about comma-separated lists here:

More Answers (3)

dpb on 5 May 2019
Is expressly noted that ML does NOT support array indexing for more than a single struct array element expression--see Note @ Unfortunate, but true...
It seems by documentation one should be able to use getfield to write a generic expression to do so, but I've never been able return what I thought should be returned by what (pretty opaque) documentation seems to infer should work..
>> getfield(rec,{1,3},'datarow',{3})
ans =
would appear that should return two values but somehow is only one. I've no explanation for what's going on here.
Such kinds of issues are why I've basically given up even trying more complicated things with struct, the grief just ain't been worth the potential benefit without a real application to make use thereof... :)
For your problem; best I've been able to do would be two-step process; you can return the whole field from the struct array as a 2D array and then do the column selection from that array. That could be wrapped in a user-function for syntax ease, but I've figured no way to write the indexing expression you would like.
You could, I think, (but I've not pursued) use the arrayfun() route with anonymous function that would operate on the element and just catenate the results, but that's a lot of overhead and obfuscation.

Image Analyst
Image Analyst on 5 May 2019
Try this:
allValues = [rec.datarow]; % String together into single vector.
allendvalues = allValues(5:5:end) % Subsample. Assumes all datarows have 5 elements
  1 Comment
dpb on 5 May 2019
My suggested soltuion, IA, as the two-step process... :)
Octave has such second-level addressing syntax features for at least some constructs; whether it's general for struct arrays I don't know. While I recognize it's undoubtedly tough nut for the parser in general, surely seems need for TMW to go this route -- I think it would be much more valuable than many of the things they have introduced recently, meself....

Sign in to comment.

Raptrick on 7 May 2019
Thanks everybody for the links, hints and considerations!


Find more on Structures in Help Center and File Exchange




Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!