Can the values โโof this structure be accessed or changed without using a for loop?
Here is my original structure array:
A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';
I want to change field values C
based on values Values
and indices IndexingArray
:
Values = {'a', 'b'};
IndexingArray = [1 1 0 1];
So my new structural array would be:
A(1).B.C = 'b';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'b';
Is there a way to do this without using a for loop?
source to share
You can do this without looping, using deal
, and comma-separated list , but it might look a bit more complicated:
% Initialize A:
A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';
Values = {'a', 'b'};
IndexingArray = [1 1 0 1];
temp = [A.B]; % Structure array containing B substructures
[temp.C] = deal(Values{IndexingArray+1}); % Set field C of each structure element
temp = num2cell(temp); % Convert to a cell array of 1-by-1 structures
[A.B] = deal(temp{:}); % Update B substructures
And in newer versions of MATLAB, you can omit altogether deal
:
temp = [A.B]; [temp.C] = Values{IndexingArray+1}; temp = num2cell(temp); [A.B] = temp{:};
This will allow you to update the fields B
and C
without affecting any other fields that may exist in your more complex structure.
source to share
Instead of changing the value, it is easier to rebuild the structure array.
-
Get value
IndexingArray
:val = Values(IndexingArray+1);
-
Create an array of structures with
cell2struct
and convert to a cell array withnum2cell
:T = num2cell(cell2struct(val, {'C'}, 1));
-
Convert the result
T
to an array of structures withcell2struct
:A = cell2struct(T', {'B'}, 1);
Here's some sample code to create A:
Values = {'a', 'b'};
IndexingArray = [1 1 0 1];
val = Values(IndexingArray+1);
T = num2cell(cell2struct(val, {'C'}, 1));
A = cell2struct(T', {'B'}, 1);
Building A in one line of code:
A = cell2struct((num2cell(cell2struct(Values(IndexingArray+1), {'C'}, 1)))', {'B'}, 1);
Result (for testing):
>> A(1).B.C ans = b >> A(2).B.C ans = b >> A(3).B.C ans = a >> A(4).B.C ans = b
Solution using arrayfun
:
val = Values(IndexingArray+1);
A = arrayfun(@(x) struct('B', struct('C', val{x})), 1:4)
Update specific A elements:
If you need to update certain elements instead of overwriting A
, you can arrayfun
selectively apply to the indices that you know you need to update.
Example:
Suppose the A
length is 6 elements and you need to update the first 4, you can use the following code:
A(1:4) = arrayfun(@(x) struct('B', struct('C', val{x})), 1:4);
Suppose you know you only need to update A(1)
and A(4)
, you can use the following example:
A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';
A(5).B.C = 'c';
A(6).B.C = 'd';
Values = {'a', 'b'};
IndexingArray = [1 1 0 1];
val = Values(IndexingArray+1);
%List of indices of A to update
indices = [1, 4];
A(indices) = arrayfun(@(x) struct('B', struct('C', val{x})), indices);
source to share