在 Matlab 中搜索多维数组中的一维序列

Search for 1-D sequence in multidimensional array in Matlab

我有一个 n 维数组,并且我在所有其他维度上的某个位置沿一个维度有一个序列。我如何找到这个序列的位置?最好没有循环。

我用的是matlab。我知道它应该在哪个维度,但顺序不一定在那里。查找和 == 不起作用。我可以使用互相关创建一个 nd find 函数,但我猜这已经实现了,我只是不知道要调用什么函数。

示例:

ND = rand(10,10,10,10);
V = ND(randi(10),randi(10),randi(10),:);
[I1, I2, I3] = find(ND==V);

编辑:要找到的序列跨越它所在的整个维度,我在问题的原始表述中没有提到这一点。 Knedlsepp 的解决方案完全解决了我遇到的问题,但 Luis 的解决方案解决了一个更普遍的问题,即当序列不一定跨越整个维度时。

由于有多种方法可以解释您的问题,我将澄清:此方法假定一维序列大小:numel(V) == size(ND, dimToSearch)。因此,对于 V = [1,2]ND = [1,2,1,2] 它不适用。如果您想要此功能,请使用 Luis Mendo 的答案,否则这可能会更快。

这将是使用 bsxfun:

的绝好机会

我们从一些示例数据开始:

ND = rand(10,10,10,10);
V = ND(3,2,:,3);

如果您没有以正确的维度给出向量 V(在本例中为 [1,1,10,1]),您可以按以下方式对其进行整形:

dimToSearch = 3;
Vdims = ones(1, ndims(ND)); 
Vdims(dimToSearch) = numel(V);
V = reshape(V, Vdims);

现在我们生成一个单元格来保存匹配项的索引:

I = cell(1, ndims(ND));

此时我们计算 ND 的大小,如果它沿着维度 dimToSearch 折叠(我们根据 V 计算 dimToSearch,因为此时它将具有正确的尺寸):

dimToSearch = find(size(V)>1);
collapsedDims = size(ND); 
collapsedDims(dimToSearch) = 1;

最后是我们实际寻找模式的部分:

[I{:}] = ind2sub(collapsedDims, find(all(bsxfun(@eq, ND, V), dimToSearch)));

这是通过以下方式完成的:bsxfun(@eq, ND, V) 将隐式 repmat 数组 V 因此它与 ND 具有相同的维度并进行相等比较。在此之后,我们使用 all 检查维度 dimToSearch 中的所有条目是否相等。然后调用 findind2sub 将为您的数据生成正确的索引。

一种不太理想的方法:

    dims = size(ND);
    Vrep = repmat(V, [dims(1), dims(2), dims(3), 1]);
    ND_V_dist = sqrt(sum(abs(ND.^2-Vrep.^2), 4));
    iI = find(ND_V_dist==0);
    [I1, I2, I3] = ind2sub([dims(1), dims(2), dims(3)], iI);

d 为搜索的维度。我假设寻找的序列 V 可能比 size(ND,d) 短。所以序列可能出现一次,不止一次,或者永远不会出现在每个维度上-d-"thread".

以下代码使用 num2cell to reshape ND into a cell array such that each dimension-d-thread is in a different cell. Then strfind 应用于每个单元格以确定与 V 的匹配,结果是一个与 ND 具有相同维度的单元格数组,但其中维度 d 是单例。每个单元格的内容告诉匹配的 d-维位置,如果有的话。

感谢 @knedlsepp 提出的使用 num2cell 的建议,这大大简化了代码。

ND = cat(3, [1 2 1 2; 3 4 5 6],[2 1 0 5; 0 0 1 2] ); %// example. 2x4x2
V = 1:2; %// sought pattern. It doesn't matter if it's a row, or a column, or...
d = 2; %// dimension along which to search for pattern V
result = cellfun(@(x) strfind(x(:).', V(:).'), num2cell(ND,d), 'UniformOutput', 0);

这给

ND(:,:,1) =
     1     2     1     2
     3     4     5     6
ND(:,:,2) =
     2     1     0     5
     0     0     1     2

V =
     1     2

result{1,1,1} =
     1     3    %// V appears twice (at cols 1 and 3) in 1st row, 1st slice
result{2,1,1} =
     []         %// V doesn't appear in 2nd row, 1st slice
result{1,1,2} =
     []         %// V appears appear in 1st row, 2nd slice
result{2,1,2} =
     3          %// V appears once (at col 3) in 2nd row, 2nd slice