sum across dynamic field names in structure
조회 수: 6 (최근 30일)
이전 댓글 표시
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
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
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
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.
댓글 수: 0
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)));
댓글 수: 0
참고 항목
카테고리
Help Center 및 File Exchange에서 Data Type Conversion에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!