Finding smallest value in nested structure
조회 수: 7 (최근 30일)
이전 댓글 표시
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!
댓글 수: 0
답변 (3개)
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
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
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
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
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)
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)
댓글 수: 0
참고 항목
카테고리
Help Center 및 File Exchange에서 File Operations에 대해 자세히 알아보기
제품
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!