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

时间:2015-01-19 14:51:55

标签: matlab multidimensional-array find

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

我使用matlab。我知道它应该是什么尺寸,但顺序不一定存在。查找和==不工作。我可以使用crosscorrelation创建一个nd find函数,但我猜这已经实现了,我只是不知道要调用什么函数。

示例:

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

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

3 个答案:

答案 0 :(得分:4)

由于有多种方法可以解释您的问题,我将澄清:此方法假定大小为1D序列: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折叠(我们根据dimToSearch计算V,因为此时它会有正确的尺寸):

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的调用将为您的数据生成正确的索引。

答案 1 :(得分:2)

d成为搜索的维度。我假设所寻求的序列V可能比size(ND,d)短。因此,序列可能会出现一次,不止一次,或永远不会出现在每个维度上 - d - "线程"。

以下代码使用num2cellND重新整形为单元格数组,以便每个维度 - d - 线程位于不同的单元格中。然后将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

答案 2 :(得分:0)

这不是一种非常理想的方式:

    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);