Finding smallest value in nested structure

7 visualizaciones (últimos 30 días)
B
B el 30 de Ag. de 2012
Respondida: Jos (10584) el 17 de Mzo. de 2015
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!

Respuestas (3)

Robert Cumming
Robert Cumming el 30 de Ag. de 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 comentarios
B
B el 30 de Ag. de 2012
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 el 17 de Mzo. de 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().

Iniciar sesión para comentar.


Image Analyst
Image Analyst el 30 de Ag. de 2012
Editada: Image Analyst el 30 de Ag. de 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 comentarios
Darik
Darik el 30 de Ag. de 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
Image Analyst el 30 de Ag. de 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.

Iniciar sesión para comentar.


Jos (10584)
Jos (10584) el 17 de Mzo. de 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)

Categorías

Más información sobre File Operations en Help Center y File Exchange.

Productos

Community Treasure Hunt

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

Start Hunting!

Translated by