Reputation: 9875
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);
Upvotes: 0
Views: 1539
Reputation: 795
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).
Upvotes: 0
Reputation: 4875
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
Upvotes: 2
Reputation: 8401
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.
Upvotes: 2