Finding smallest value in nested structure

조회 수: 7 (최근 30일)
B
B 2012년 8월 30일
답변: Jos (10584) 2015년 3월 17일
Dear all,
I have a structure as shown here:
subject(i).cineLoop.frame(j).data(k).area
Where 'area' is an amount (e.g. 2328).
How can I find the smallest area in the entire structure? Do I have to resort to for loops? Or am I better off using a different kind of container?
I found another thread concerning this problem: http://www.mathworks.nl/matlabcentral/answers/40479-multi-level-indexing , however I didn't manage to get the solution working for structures with more than 2 levels.
Any help is much appreciated!

답변 (3개)

Robert Cumming
Robert Cumming 2012년 8월 30일
One way is to use a self calling function (this will find "area" at any level):
Here is the bones of one - you would call it by:
( yourStruct, 'area' );
function SelfCallingFunction ( str, var )
fnames = fieldnames ( str );
for i=1:length(fnames)
if strcmp ( fnames{i}, var )
disp ( str.(fnames{i} ) );
elseif isstruct ( str.(fnames{i}) )
SelfCallingFunction ( str.(fnames{i}), var )
end
end
end
Note: This will only display the variable in question - but you can expand on this to make it store the "area" and returned it.
There is a bit more work to do - and you really need to do it yourself to learn how it works but also to be able to maintain the code in the future.
  댓글 수: 4
B
B 2012년 8월 30일
Thanks for your reply. I'm glad to hear that for loops are the way to go. I've been using MATLAB for a while now, making the transitition from C++. Since a lot of containers from STL have their own syntax to handle data, I was wondering whether I was overlooking some basic functionality of MATLAB.
Jeremy S
Jeremy S 2015년 3월 17일
Looping through the fieldnames() output is unfortunately the way to do it. Its a little easier if you put a number in the fieldname, i.e. area1, area2, etc... and then use a strcat(['area',str2num(i)]) in a for loop instead of using fieldnames().

댓글을 달려면 로그인하십시오.


Image Analyst
Image Analyst 2012년 8월 30일
편집: Image Analyst 2012년 8월 30일
Just a guess. Try this (untested):
allAreas = [subject.cineLoop.frame.data.area];
[minArea, indexOfMin] = min(allAreas);
I know it works for cell arrays, such as you get from regionprops(). Add indexes at places if you want to narrow it down. However the index is the index into allAreas, not the i, j, and k separately. You might have to keep track of the min as you traverse your triple for loop if you want to know the i, j, and k individually.
  댓글 수: 3
Darik
Darik 2012년 8월 30일
I think you might have to concatenate one level at a time
allCineLoops = [subject.cineLoop];
allFrames = [allCineLoops.frame];
allData = [allFrames.data];
allArea = [allData.area];
minArea = min(Area);
Image Analyst
Image Analyst 2012년 8월 30일
Try this:
clc;
% Generate some sample data
for i = 1 : 3
for j = 1 : 4
for k = 1 : 5
subject(i).cineLoop.frame(j).data(k).area = rand(1);
end
end
end
tic; % Start timer.
% Now find the smallest area.
% First initialize the min values we want to keep track of.
iAtMinArea = 1;
jAtMinArea = 1;
kAtMinArea = 1;
minArea = inf;
% Now scan the structure looking for the global min.
for i = 1 : 3
for j = 1 : 4
for k = 1 : 5
if subject(i).cineLoop.frame(j).data(k).area < minArea
iAtMinArea = i;
jAtMinArea = j;
kAtMinArea = k;
minArea = subject(i).cineLoop.frame(j).data(k).area;
end
end
end
end
% Found it. Now print them to the command window
toc; % Stop timer and print out elasped time.
fprintf('The min area = %f and occurs at i = %d, j = %d, k = %d.\n',...
minArea, iAtMinArea, jAtMinArea, kAtMinArea)
% Typical printout:
% Elapsed time is 0.001091 seconds.
% The min area = 0.010271 and occurs at i = 3, j = 3, k = 5.

댓글을 달려면 로그인하십시오.


Jos (10584)
Jos (10584) 2015년 3월 17일
I think the for-loop approach is the best option. You can use that to store each value in a matrix first:
Ni = numel(subject)
Nj = numel(subject(1).cineLoop.frame)
Nk = numel(subject(1).cineLoop.frame(1).data)
Area = zeros(Nk,Nj,Nk) ;
for i=1:Ni
for j=1:Nj
for k=1:Nk
Area(i,j,k) = subject(i).cineLoop.frame(j).data(k).area ;
end
end
end
[MinArea, idx) = min(Area(:))
[mi,mj,mk] = ind2sub([Ni,Nj,Nk],idx)

카테고리

Help CenterFile Exchange에서 File Operations에 대해 자세히 알아보기

제품

Community Treasure Hunt

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

Start Hunting!

Translated by