Get Smart, Be Logical!
Recently a customer asked me an interesting question about a good way to compute something. Before I sat down to tackle it, I happened to mention the problem to my pal, Sean. And he quickly answered, "max logical". It took me just a moment to realize what he was saying, and it is the answer to the problem. But when I heard it, I heard a person's name "Max Logical", and though I didn't know who that was, I immediately thought of Maxwell Smart, from the 60s tv comedy in the US, called "Get Smart".
By General Artists Corporation-GAC-management. [Public domain], via Wikimedia Commons
And you can see the precursor to today's mobile phones!
Contents
The Problem
So what's the problem? The customer posed it by way of an example. Given a 3-D array A, generated for this example from a matrix, find the first plane in which some condition is true.A=[1 2; 3 4] M = cat(3, A, A+1, A+2, A+3);
A = 1 2 3 4So the function should work like this: IDX = someFunction(M >=5);
IDX = [NaN 4; 3 2]
IDX = NaN 4 3 2And, the customer wanted this to work for arrays of higher dimensions as well.
The Solution
As I said, I mentioned this to Sean. But I had thought for about 2 seconds about it before and I realized I could do a find on the entire array, as if it were a vector, get the locations and sort them into their proper locations and find the first one in the correct last dimension. And then Sean said "Max Logical". Here's what a great solution looks like.catdim = 3; szA = size(A); [mv,midx] = max(M >= 5,[],catdim); IDX = NaN(szA); IDX(mv) = midx(mv)
IDX = NaN 4 3 2Why/how did this work? Well, I use the condition I want met into function max, and it is logical input, meaning only 0s and 1s. And max returns the index where the first condition is met, and I do this along the final dimension. Then create an array of NaN values, and use logical indexing to update this index matrix. Voila!
Higher Dimensions
Now let's see if it makes sense in higher dimensions. For simplicity, I again will provide a base array in 1 dimension less than I am ultimately looking, so I can construct something for which I can reasonably easily check the result.A = randi(17, [3 2 1 3]); catdim = ndims(A)+1 M = cat(catdim, A, A+1, A+2, A+3, A+4);
catdim = 5See a slice of M
sliceOfM = M(:,:,:,1)
sliceOfM = 12 2 13 4 8 16Apply the max, logical indexing to M next.
szA = size(A) [mv,midx] = max(M >= 13,[],catdim); IDX = NaN(szA); IDX(mv) = midx(mv)
szA = 3 2 1 3 IDX(:,:,1,1) = 2 NaN 1 NaN NaN 1 IDX(:,:,1,2) = NaN 1 1 NaN 4 NaN IDX(:,:,1,3) = NaN 1 1 1 NaN 1
Have You Embraced Logical Indexing?
I have made several posts over the years on indexing that readers have found helpful. Do you have any interesting logical stories to share? Post them here. Published with MATLAB® R2017b- Category:
- Indexing
Comments
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.