问题描述
我有一个 3D 逻辑数组,例如:
I have a 3D logical array, for example:
A = randi([0 1],x,y,z);
其中 x,y,z 是整数.
where x,y,z are integers.
有没有办法为每个 (x,y) 找到沿第三维z"的第一个真值?
Is there a way to find the first true value along the 3rd dimension 'z', for each (x,y)?
我可以这样循环:
B = zeros(x,y);
for ix = 1:x
for iy = 1:y
B(ix,iy) = find(A(ix,iy,:),1,'first');
end
end
是否有一个数组操作可以让我在没有循环的情况下进行操作?
Is there an array operation which will allow me to do it without a loop?
推荐答案
不是一个很简单的解决方案.
Not a very straightforward one.
那是因为在第三维的任何地方都可能存在 true
.
That is because there may not be a true
anywhere along the third dimension.
顺便说一句,您正在做的事情可能会导致一个非常难以找到的错误.如果某处没有真值,find
将返回空矩阵([]
).并且,在 MATLAB 中将一个空矩阵分配给某个元素会删除您要分配到的数组中的那个元素.
By the way, what you're doing may lead to an extremely hard to find bug. If it is the case that there is no true value somewhere, find
will return the empty matrix ([]
). And, assigning an empty matrix to something in MATLAB will delete that element from the array you're assigning to.
意思:
B(ix,iy)
将被删除B
中的元素数量将减少 1- 所有后续结果都会被分配到
B
中的错误位置 - 当您到达
A
的末尾时(因此现在索引超出了B
的边界),MATLAB 将自动增长数组B
以适应您的任务.
B(ix,iy)
will be deleted- The number of elements in your
B
will shrink by 1 - All subsequent results will be assigned to the wrong positions in
B
- When you've reached the end of
A
(and are thus now indexing beyond the boundary ofB
), MATLAB will automatically grow the arrayB
to fit your assignment.
你不会更聪明,但所有的结果都是毫无意义的垃圾.
You'll be none the wiser, but all the results are meaningless garbage.
幸运的是,如果您对维度大于 1 的数组执行此操作,MATLAB 会抛出警告,但是,如果您在 vectors(例如,B
是一个向量),MATLAB 不会警告您.
Luckily, MATLAB throws a warning if you're doing that on arrays with dimension larger than 1, BUT, if you're using the same technique on vectors (e.g., B
is a vector), MATLAB will not warn you.
所以,至少,做一个检查:
So, at the very least, do a check:
for ix = 1:x
for iy = 1:y
if any(A(ix,iy,:))
B(ix,iy) = find(A(ix,iy,:), 1, 'first');
end
end
end
还请注意,any
可以接受第二个参数,指定维度为any
",意思是
Also note that any
can take a second argument specifying the dimension to "any
" over, meaning
any(A,3)
将返回一个x×y
逻辑数组,如果A
中有true
,则包含true
沿其第三维,否则为 false
.这可以帮助您避免必须显式计算索引(通常,如果您更改范式,它们并不是真正需要的).
will return an x×y
array of logicals, containing true
if there is a true
in A
along its third dimension, and false
otherwise. This may help you prevent having to compute the indices explicitly (oftentimes, they are not really explicitly needed if you change paradigm).
现在,说了这么多,你可以使用
Now, having said all that, you could use
[~, B] = max(A ~= 0, [], 3);
但您仍然需要对全零进行检查:
but you'd still have to do checks on all-zeros:
B(~any(A, 3)) = 0;
我想说,带有检查的循环只是所以更直观,它会符合我的偏好.然而,max
技术快了大约 7 倍,所以当正确记录时(可能将循环作为其上方注释的一部分,以及在随附的单元测试中),那么,为什么不.
I'd say, the loop with the check is just so much more intuitive that it'd have my preference. However, the max
technique is about 7 times faster, so when properly documented (probably with the loop as part of the comment above it, as well as in an accompanying unit test), then well, why not.
这篇关于仅在第 3 维的 3D 逻辑数组中使用 Matlab“查找"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!