查找矩阵中不同值的行索引

find row indices of different values in matrix

将矩阵 A (n*2) 作为源,将 B 作为包含元素 A 子集的向量,我想找到项目的行索引。

A=[1 2;1 3; 4 5];
B=[1 5];
F=arrayfun(@(x)(find(B(x)==A)),1:numel(B),'UniformOutput',false)

在单元格中给出以下输出 according to this help page

[2x1 double]    [6]

按列表示所有出现的索引。但我想要行的索引。即我想知道元素 1 出现在第 1 行和第 2 行中,而元素 5 恰好出现在第 3 行中。如果索引是按行排列的,我可以使用 ceil(F{x}/2) 获得所需的输出.现在行数可变,您建议的解决方案是什么?因为可能碰巧没有完整的包含标签 'rows' in ismember 函数不起作用。此外,我想知道指定元素的所有索引。 在此先感谢您的帮助。

方法一

从当前的 linear-index form into row indices, use mod 转换 F:

rows = cellfun(@(x) mod(x-1,size(A,1))+1, F, 'UniformOutput', false);

您可以将其与您的代码合并成一行。另请注意,您可以直接使用 B 作为 arrayfun 的输入,并且避免了一个索引阶段:

rows = arrayfun(@(x) mod(find(x==A)-1,size(A,1))+1, B(:), 'UniformOutput', false);

这是如何工作的:

F 您的代码给出的是列优先形式的线性索引。这意味着索引沿着 B 的第一列向下运行,从第二列的顶部开始并再次向下运行,等等。因此可以仅通过模数 (mod) 获得行号操作。

方法二

使用bsxfun and accumarray

t = any(bsxfun(@eq, B(:), reshape(A, 1, size(A,1), size(A,2))), 3); %// occurrence pattern
[ii, jj] = find(t); %// ii indicates an element of B, and jj is row of A where it occurs
rows = accumarray(ii, jj, [], @(x) {x}); %// group results according to ii

这是如何工作的:

假设 AB 如您的示例所示,t 是 2x3 矩阵

t =
     1     1     0
     0     0     1

mt 行包含 1 在第 n 列,如果 m-B 的第 n 行出现在 B 的第 n 行。这些值被转换成行和列的形式 find:

ii =
     1
     1
     2
jj =
     1
     2
     3

这意味着 B 的第一个元素出现在 A 的第 1 行和第 2 行;第二个出现在 B.

的第 3 行

最后,jj 的值根据 ii 的对应值进行分组(使用 accumarray)以生成所需的结果。

一种方法 bsxfun & accumarray -

%// Create a match of B's in A's with each column of matches representing the
%// rows in A where there is at least one match for each element in B 
matches = squeeze(any(bsxfun(@eq,A,permute(B(:),[3 2 1])),2))

%// Get the indices values and the corresponding IDs of B
[indices,B_id] = find(matches)
%// Or directly for performance:
%// [indices,B_id] = find(any(bsxfun(@eq,A,permute(B(:),[3 2 1])),2))

%// Accumulate the indices values using B_id as subscripts
out = accumarray(B_id(:),indices(:),[],@(x) {x})

样本运行-

>> A
A =
     1     2
     1     3
     4     5
>> B
B =
     1     5
>> celldisp(out) %// To display the output, out
out{1} =
     1
     2
out{2} =
     3

arrayfun,ismember and find

[r,c] = arrayfun(@(x) find(ismember(A,x)) , B, 'uni',0);

其中 r 给出了您想要的结果,您还可以使用 c 变量来获取 B

中每个数字的列

示例输入的结果:

>> celldisp(r)

r{1} =
 1
 2

r{2} = 
 3


>> celldisp(c)

c{1} = 
 1
 1

c{2} =
 2