Finding smallest value in nested structure
7 views (last 30 days)
Show older comments
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 Comments
Answers (3)
Robert Cumming
on 30 Aug 2012
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 Comments
Jeremy S
on 17 Mar 2015
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
on 30 Aug 2012
Edited: Image Analyst
on 30 Aug 2012
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 Comments
Darik
on 30 Aug 2012
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
on 30 Aug 2012
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)
on 17 Mar 2015
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 Comments
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!