sum across dynamic field names in structure
10 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
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 Kommentare
Cedric
am 24 Jun. 2014
Bearbeitet: Cedric
am 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.
Antworten (3)
John D'Errico
am 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
am 24 Jun. 2014
Bearbeitet: Sean de Wolski
am 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.
0 Kommentare
José-Luis
am 24 Jun. 2014
Bearbeitet: José-Luis
am 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)));
0 Kommentare
Siehe auch
Kategorien
Mehr zu Data Type Conversion finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!