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.

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 CenterFile Exchange에서 Data Type Conversion에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by