1
\$\begingroup\$

I am attempting to find the maximum value and its location in multidimensional array using Matlab. There are functions findMax3, findMax4, findMax5 and findMax6 for dealing with different dimension cases.

The experimental implementation

function [maxNum, v1, v2, v3] = findMax3(input3d)
    maxNum = max(input3d, [], 'all');
    index = find(input3d(:) == maxNum );
    %The dimensions of the array needs to be fed as an input to ind2sub function
    [v1, v2, v3] = ind2sub(size(input3d),index);
end

function [maxNum, v1, v2, v3, v4] = findMax4(input4d)
    maxNum = max(input4d, [], 'all');
    index = find(input4d(:) == maxNum );
    %The dimensions of the array needs to be fed as an input to ind2sub function
    [v1, v2, v3, v4] = ind2sub(size(input4d),index);
end

function [maxNum, v1, v2, v3, v4, v5] = findMax5(input5d)
    maxNum = max(input5d, [], 'all');
    index = find(input5d(:) == maxNum );
    %The dimensions of the array needs to be fed as an input to ind2sub function
    [v1, v2, v3, v4, v5] = ind2sub(size(input5d),index);
end

function [maxNum, v1, v2, v3, v4, v5, v6] = findMax6(input6d)
    maxNum = max(input6d, [], 'all');
    index = find(input6d(:) == maxNum );
    %The dimensions of the array needs to be fed as an input to ind2sub function
    [v1, v2, v3, v4, v5, v6] = ind2sub(size(input6d),index);
end

Test cases

% Unit tests for findMax function

%%  Three-dimensional case

sizeNum = 10;
TestArray = zeros(sizeNum, sizeNum, sizeNum);
TestArray(1, 2, 3) = 1;
[maxNum, v1,v2,v3] = findMax3(TestArray)

%%  Four-dimensional case

sizeNum = 10;
TestArray = zeros(sizeNum, sizeNum, sizeNum, sizeNum);
TestArray(1, 2, 3, 4) = 1;
[maxNum, v1, v2, v3, v4] = findMax4(TestArray)

%%  Five-dimensional case

sizeNum = 10;
TestArray = zeros(sizeNum, sizeNum, sizeNum, sizeNum, sizeNum);
TestArray(1, 2, 3, 4, 5) = 1;
[maxNum, v1, v2, v3, v4, v5] = findMax5(TestArray)

%%  Six-dimensional case

sizeNum = 10;
TestArray = zeros(sizeNum, sizeNum, sizeNum, sizeNum, sizeNum, sizeNum);
TestArray(1, 2, 3, 4, 5, 6) = 1;
[maxNum, v1, v2, v3, v4, v5, v6] = findMax6(TestArray)

All suggestions are welcome.

\$\endgroup\$
1
\$\begingroup\$

Did you consider what would happen if there are more than one element in the array with the same maximum value? max returns one of them, but your find will return the index to all of them.

One solution is to use the new syntax for max: [M,I] = max(A,[],___,'linear') (I don’t know when it was introduced, but I just learned about it now).

This syntax is equal to the old-fashioned [M,I] = max(A(:)), which will work even in 20-year-old versions of MATLAB. Note that A(:) creates a vector, but doesn’t copy data, it is an essentially free operation.

The I output is the linear index, just as returned by find, except it’s always a single value. This is also faster because there is no need to create the intermediate array input3d(:) == maxNum.

The next thing I would do is find a way to combine all these functions into a single one that works for any number of dimensions. This requires solving the conundrum of calling ind2sub with the right number of output arguments. There’s a trick for that:

coords = cell(1, ndims(A));
[coords{:}] = ind2sub(size(A), I);

You could then put the coordinates into a regular array: coords = [coords{:}], to make the function easier to use.

In your unit tests, use assert to verify that the outputs have the expected values:

sizeNum = 10;
TestArray = zeros(sizeNum, sizeNum, sizeNum);
TestArray(1, 2, 3) = 1;
[maxNum, v1,v2,v3] = findMax3(TestArray);
assert(maxNum = 1)
assert(v1 == 1);
assert(v2 == 2);
assert(v3 == 3);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.