Suppose I have a struct array arr
, where each element has a bunch of fields, including one called val
. I'd like to increment each element's val
field by some constant amount, like so:
for i = 1:length(arr) arr(i).val = arr(i).val + 3; end
This obviously works, but I feel there should be a way to do this in just one line of code (and no for loop). The best I've come up with is two lines and requires a temp variable:
newVals = num2cell([arr.val] + 3); [arr.val] = deal(newVals{:});
Any ideas? Thanks.
S = setfield( S , field , value ) assigns a value to the specified field of the structure S . For example, S = setfield(S,'a',1) makes the assignment S.a = 1 . As an alternative to setfield , use dot notation: S. field = value .
You can create an array of structures from a scalar structure by using the MATLAB repmat function, which replicates and tiles an existing scalar structure: Create a scalar structure, as described in Define Scalar Structures for Code Generation.
Arrays with named fields that can contain data of varying types and sizes. A structure array is a data type that groups related data using data containers called fields. Each field can contain any type of data. Access data in a structure using dot notation of the form structName.
Just a note, the deal
isn't necessary there:
[arr.val] = newVals{:}; % achieves the same as deal(newVals{:})
The only other way I know how to do this (without the foor loop) is using arrayfun
to iterate over each struct in the array:
% make a struct array arr = [ struct('val',0,'id',1), struct('val',0,'id',2), struct('val',0,'id',3) ] % some attempts [arr.val]=arr.val; % fine [arr.val]=arr.val+3; % NOT fine :( % works ! arr2 = arrayfun(@(s) setfield(s,'val',s.val+3),arr)
That last command loops over each struct in arr
and returns a new one where s.val
has been set to s.val=3
.
I think this is actually less efficient than your previous two-liner and the for loop though, because it returns a copy of arr
as opposed to operating in-place.
(It's a shame Matlab doesn't support layered indexing like [arr.val]=num2cell([arr.val]+3){:}
).
I like Carl's and mathematical.coffee's original ideas. I have multiple similar lines to express, so for concision of my mainline code, I went ahead and made the generic subfunction
function varargout = clist(in) varargout = {in{:}}; end
then I could express each such line in a fairly readable way
[arr.var] = clist(num2cell([arr.var]+3)); [arr.var2] = clist(num2cell([arr2.var]/5+33));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With