sum across dynamic field names in structure

6 ビュー (過去 30 日間)
Keith
Keith 2014 年 6 月 24 日
編集済み: Cedric 2014 年 6 月 24 日
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 件のコメント
Keith
Keith 2014 年 6 月 24 日
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 2014 年 6 月 24 日
編集済み: Cedric 2014 年 6 月 24 日
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.

サインインしてコメントする。

回答 (3 件)

John D'Errico
John D'Errico 2014 年 6 月 24 日
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.
  1 件のコメント
Keith
Keith 2014 年 6 月 24 日
thanks - good suggestion.

サインインしてコメントする。


Sean de Wolski
Sean de Wolski 2014 年 6 月 24 日
編集済み: Sean de Wolski 2014 年 6 月 24 日
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 2014 年 6 月 24 日
編集済み: José-Luis 2014 年 6 月 24 日
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)));

カテゴリ

Help Center および File ExchangeData Type Conversion についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by