0

I want to set multiple fields in a struct to a single value. The fields are potentially new. And the field names are potentially dynamically defined. The number of field names is dynamically defined. Is there any good way to do it?

For example, the following works if the number of field names is fixed. But it is tedious and silly. And it does not work if the number of field names is allowed to change.

S=struct;
[S.f1,S.f2,S.f3]=deal(input);
2
  • Will the fields always be like f1, f2, etc. (i.e., letter-number pairs)? Or more complicated/arbitrary? Commented Mar 13, 2015 at 20:51
  • I can work with any particular syntax. I used letter-number pair in the example because Matlab requires a preceding letter in field names. Thank you. Commented Mar 13, 2015 at 21:05

3 Answers 3

2

For letter-number pairs (e.g., f1, f2, etc.), I'd suggest using struct-arrays for initialization. You can create them by passing a cell array to the struct function of the values you'd like:

ini = 1;
n   = 5;
s = struct('f',repmat({ini},n,1));

Then s is a struct array with initial values ini. You can access elements like s(1).f .... s(n).f. You can also use the deal function with a struct array literal, which I think it cleaner, like this;

ini = 1;
n   = 5;
s(n).f = [];
[s.f] = deal(ini);

For more generic fieldnames, @CitizenInsane's answer using dynamic field references is the only way I know of as well.

This could change if MATLAB would create comma-separated lists from dynamic fields with cell string arguments, but that is but a dream of mine.

Sign up to request clarification or add additional context in comments.

2 Comments

One like for the answer. Another like for that awesome dream of yours. How do I give two likes?
@Argyll I gave the second like ;)
2

The most simple thing I can think of for now is:

function [myStruct] = InitStruct(myStruct, initValue)
%[
    % Default arguments for demo purpose
    if (nargin < 2), initValue = 42; end
    if (nargin < 1), myStruct = struct('f1', '', 'f2', '', 'f3', ''); end

    % Obtain all current fields in the structure
    fnames = fieldnames(myStruct); 

    % Dynamically set all fields with initValue
    for fi = 1:length(fnames),
        myStruct.(fnames{fi}) = initValue; 
    end
%]
end

NB: It only works if the structure is scalar ... to encompass all case you can add a loop on structure's length:

function [myStruct] = InitStruct(myStruct, initValue)
%[
    if (nargin < 2), initValue = 42; end
    if (nargin < 1), 
        myStruct = struct('f1', '', 'f2', '', 'f3', '');
        myStruct = repmat(myStruct, [2 6]); % Making structure not scalar
    end

    fnames = fieldnames(myStruct);
    for fi = 1:length(fnames),
        for linearIndex = 1:length(myStruct),
            myStruct(linearIndex).(fnames{fi}) = initValue;
        end
    end
%]
end

2 Comments

Ic. So fieldnames plus a loop.
@Argyll Yes, so far I don't see simpler way to do it.
0

What about this ?

S = struct('f1', 1, 'f2', 2);
old_fields = fieldnames(S);
old_values = struct2cell(S);

new_fields = {'f2'; 'f3'; 'f4'}; % 1 replacement, 2 new fields
n_new_fields = numel(new_fields);
value = 0;

all_fields = [old_fields ; new_fields];
all_values = [old_values ; repmat({value}, n_new_fields, 1)];
S = cell2struct(all_values, all_fields);

I am not sure Matlab won't return an error for having twice the same field (can't test right now). If so, you'll need to use

[all_fields, idx] = unique(all_fields);
all_values = all_values(idx);

before calling cell2struct (just be careful as Matlab has changed the behavior of unique in the most recent releases).

1 Comment

hi, I still need to read your response. but in a quick note, Matlab doesn't complain for having two field names pointing to the same object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.