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?

+3


source to share


2 answers


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.

+3


source


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 with num2cell

    :

    T = num2cell(cell2struct(val, {'C'}, 1));
    
          

  • Convert the result T

    to an array of structures with cell2struct

    :

    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);

      

+1


source







All Articles