3

I'm currently trying to find the min/max value of 5 different 2x1 arrays of doubles on Matlab. I wrote a function below that works, returning the min and max values from all 5 arrays listed. However, it looks so long and bulky. I was wondering if there was a more efficient way of doing this?

I was thinking of making an array of arrays, but I don't want to copy all that data and waste memory just to check for a min and max value.

Any ideas on this? Thanks!

%% Finds min/max Lat values
function results = FindRanges(hObject,handles)

% Min of Latitudes
minLat = TG_Lat;
if min(handles.AC_Lats(:)) < minLat
    minLat = min(handles.AC_Lats(:));
end
if min(handles.MS_Lats(:)) < minLat
    minLat = min(handles.MS_Lats(:));
end
if min(handles.DL_Lats(:)) < minLat
    minLat = min(handles.DL_Lats(:));
end
if min(handles.PI_Lats(:)) < minLat
    minLat = min(handles.PI_Lats(:));
end
if min(handles.EM_Lats(:)) < minLat
    minLat = min(handles.EM_Lats(:));
end

% Max of Latitudes
maxLat = TG_Lat;
if max(handles.AC_Lats(:)) > maxLat
    maxLat = max(handles.AC_Lats(:));
end
if max(handles.MS_Lats(:)) > maxLat
    maxLat = max(handles.MS_Lats(:));
end
if max(handles.DL_Lats(:)) > maxLat
    maxLat = max(handles.DL_Lats(:));
end
if max(handles.PI_Lats(:)) > maxLat
    maxLat = max(handles.PI_Lats(:));
end
if max(handles.EM_Lats(:)) > maxLat
    maxLat = max(handles.EM_Lats(:));
end

results = [minLat, maxLat];
  • what is your handles object like, are the only properties the ones you are using for your min/max? – sg1234 Jun 14 '21 at 21:36

2 Answers2

3

Copying 5 2x1 arrays is no big deal. That might even be more efficient than calling the max and min function 5 times (function call overhead is a real thing in MATLAB still). So you could do:

data = [handles.AC_Lats(:); handles.MS_Lats(:); handles.DL_Lats(:); ...
        handles.PI_Lats(:); handles.EM_Lats(:)];
results = [min(data), max(data)];

If arrays are (potentially) larger, you could do this:

minLat = min([min(handles.AC_Lats(:)), min(handles.MS_Lats(:)), min(handles.DL_Lats(:)), ...
              min(handles.PI_Lats(:)), min(handles.EM_Lats(:))]);
maxLat = max([max(handles.AC_Lats(:)), max(handles.MS_Lats(:)), max(handles.DL_Lats(:)), ...
              max(handles.PI_Lats(:)), max(handles.EM_Lats(:))]);
results = [minLat, maxLat];

This is the same thing you do, but using the built-in min and max functions instead of writing them out.

PS: I've ignored your TG_Lat, not sure what that is used for. Currently it looks like a 6th data element, but it is not described in the question text.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • Thanks! Your first example worked smoothly. I realized that I messed up when writing the question: the arrays are 2000x1 arrays, so they are pretty chunky. I am not sure if arrays of that size would make any significant changes to performance using that first option you provided – Wallace Borges Jun 21 '21 at 17:46
  • 1
    @WallaceBorges: time the two options with your arrays, then use whichever is faster. 2000 elements is not big. – Cris Luengo Jun 21 '21 at 18:13
2

My current answer assumes what I believe to be the case regarding your handles object, i.e. that it only contains the information relevant to this task. If this is not the case then this will not work as it iterates through all the properties of the handles object.

data = [TG_Lat,structfun(@(x)x(1),handles)';TG_Lat,structfun(@(x)x(2),handles)'];
results = [ min(min(data)),max(max(data)) ];

I would like to also add that, although there is nothing wrong with code being a bit bulky, you make too many calls to min() and max(). Vectorization aside (which will likely not substantially change performance in this case), it seems like a good practice to avoid calling the same function twice for the same result (in the if and in the assignment).

Edit 1 Actually, it seems struct2array would be even simpler, and looking at Cris Luengo's answer putting the data in one dimension would work as well, so here's another answer that uses some of their answer ;) (I hope this is cool.)

data = [TG_Lat([1;1]),struct2array(handles)];
results = [min(data(:)),max(data(:))]
sg1234
  • 600
  • 4
  • 19
  • Nice idea to iterate over the elements of `handles`. Not sure why `x(1)` and `x(2)` are handled separately, rather than concatenating `x(:)` directly (one call to `structfun`). If you concatenate all elements in a single column vector you just need one call to `min` and one to `max`, rather than two. Still, +1. – Cris Luengo Jun 14 '21 at 21:55
  • @Cris I was writing an edit, actually. Thanks for the +1 ;) You are right there is no reason to use them separately, I think my problem was that when I first tried it I mistakingly read that the OP was using 1x2 matrices rather than 2x1. In my example, with 1x2 I had to separate the result. – sg1234 Jun 14 '21 at 22:09
  • @sg1234 Your idea would be great! Unfortunately you're right, the handles object wouldn't work for that. Handles is the default object that holds all data when using GUIDE to build apps on Matlab, meaning it not only handles variables but also holds tags for all GUI elements. So it would iterate through everything – Wallace Borges Jun 21 '21 at 17:40