sum across dynamic field names in structure

6 views (last 30 days)
Keith
Keith on 24 Jun 2014
Edited: Cedric on 24 Jun 2014
I Have a structure that has 4 fields. The first one is a static name (i.e., Date) and the next three are dynamic (i.e, Name1, Name2, Name3).
I would like to create a fourth field that is sum of Name1-3, but I want to keep it generalized so that they I can scale up in number of fields.
I would prefer that this be a vectorized function and not in a loop.
Thanks.
  3 Comments
Keith
Keith on 24 Jun 2014
Well I wanted faster, I just assumed vectorized code was faster.
All I have right now was a hard coded sum of Struct.Name1 + Struct.Name2, etc. I was thinking some sort of inline for loop:
sum(Struct.(for i=1:3, strcat('Name',i), end))),2)
But I am sure my code is wrong...
Cedric
Cedric on 24 Jun 2014
Edited: Cedric on 24 Jun 2014
If you want increase efficiency, your best option is probably to work on the reasons why you implemented dynamic field names in the first place. Dynamic field names are rarely mandatory and people often misuse them. For example, they want to store labels and data associated with these labels, and use the labels as field names, when a cleaner and more efficient approach consists in storing data in a numeric array, and labels in a cell array. If you cannot avoid using dynamic field names, maybe you can create an extra field "sum" when you build the struct, with the sum computed at this moment.

Sign in to comment.

Answers (3)

John D'Errico
John D'Errico on 24 Jun 2014
What is wrong with just using fieldnames to get a list of the fields, then drop the date field, and just use a loop over the rest of the fields?
The fact is, often a loop is NOT a time consuming thing, and vectorized code is not always a speed boost. Don't waste programming time to solve problems that are not a bottleneck.

Sean de Wolski
Sean de Wolski on 24 Jun 2014
Edited: Sean de Wolski on 24 Jun 2014
I see no reason to vectorize this operation. A for-loop will surely be the fastest and most elegant approach
%%Sample structure
S = struct('Date',num2cell(floor(now):floor(now)+9),...
'Name1',num2cell(rand(1,10)),'Howdy',num2cell(1:10))
%%Fieldnames to sum
fns = fieldnames(S);
fnsSum = fns(~ismember(fns,'Date')); % remove date
nFnsSum = numel(fnsSum);
%%Engine
for ii = numel(S):-1:1
for jj = nFnsSum:-1:1
T(jj) = S(ii).(fnsSum{jj});
end
S(ii).fnSum = sum(T);
end
%%Results
S
Also, if you are using R2013b or newer, you may wish to look into the table datatype. This is like a structure but optimized for dealing with columns of heterogenous data. For this example, we can do what you want in one simple line:
%%Sample structure->tabke
S = struct('Date',num2cell(floor(now):floor(now)+9),...
'Name1',num2cell(rand(1,10)),'Howdy',num2cell(1:10))
T = struct2table(S) % turn it into a table
T.fnSum = sum(T{:,2:end},2) % Sum everything after first column along rows.

José-Luis
José-Luis on 24 Jun 2014
Edited: José-Luis on 24 Jun 2014
This is probably going to be slower than a for loop:
a.date = now;
a.name1 = 1;
a.name2 = 2;
a.name3 = 3;
a.name4 = 4;
fieldname = 'name';
names = fieldnames(a);
data = struct2cell(a);
isName = regexp(names,['^' fieldname '[0-9]+']); %Find relevant fields
isName = cell2mat(cellfun(@(x) ~isempty(x), isName,'un', false));,,
your_sum = sum(cell2mat(data(isName)));

Categories

Find more on Data Type Conversion in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!