【发布时间】:2014-02-14 20:06:07
【问题描述】:
我有两个具有相同元素的向量,但它们的顺序不同。例如
一个
10
9
8
B
8
9
10
我想找到两者之间的映射
B2A
3
2
1
如何在 matlab 中有效地做到这一点?
【问题讨论】:
标签: matlab
我有两个具有相同元素的向量,但它们的顺序不同。例如
一个
10
9
8
B
8
9
10
我想找到两者之间的映射
B2A
3
2
1
如何在 matlab 中有效地做到这一点?
【问题讨论】:
标签: matlab
我认为 Matlab 排序是有效的。所以:
[~,I]=sort(A); %sort A; we want the indices, not the values
[~,J]=sort(B); %same with B
%I(1) and J(1) both point to the smallest value, and a similar statement is true
%for other pairs, even with repeated values.
%Now, find the index vector that sorts I
[~,K]=sort(I);
%if K(1) is k, then A(k) is the kth smallest entry in A, and the kth smallest
%entry in B is J(k)
%so B2A(1)=J(k)=J(K(1)), where BSA is the desired permutation vector
% A similar statement holds for the other entries
%so finally
B2A=J(K);
如果上述内容在脚本“findB2A”中,则应检查以下内容
N=1e4;
M=100;
A=floor(M*rand(1,N));
[~,I]=sort(rand(1,N));
B=A(I);
findB2A;
all(A==B(B2A))
【讨论】:
sort 错误。也许你得到的是“A2B”而不是B2A。看我的回答
有几种方法可以做到这一点。就代码行而言,最有效的可能是使用ismember()。返回值为[Lia,Locb] = ismember(A,B),其中Locb 是B 中的索引,对应于A 的元素。你可以[~, B2A] = ismember(A, B) 得到你想要的结果。如果您的 MATLAB 版本不允许 ~,请为第一个输出提供一次性参数。
您必须确保存在一对一的映射才能获得有意义的结果,否则索引将始终指向第一个匹配的元素。
【讨论】:
这里有一个解决方案:
arrayfun(@(x)find(x == B), A)
我尝试了更大的数组:
A = [ 7 5 2 9 1];
B = [ 1 9 7 5 2];
它给出以下结果:
ans =
3 4 5 2 1
编辑
因为arrayfun通常比等效循环慢,这里有一个循环的解决方案:
T = length(A);
B2A = zeros(1, length(A));
for tt = 1:T
B2A(1, tt) = find(A(tt) == B);
end
【讨论】:
find 一开始效率不高,对每个元素运行它也无济于事。
ismember 使用 find 函数。
我会使用三个链接的sort's 来选择Joe Serrano's answer。
另一种方法是使用bsxfun 测试所有组合是否相等:
[~, B2A] = max(bsxfun(@eq, B(:), A(:).'));
这给出了B2A,使得B(B2A) 等于A。如果您希望反过来(从您的示例中不清楚),只需在 bsxfun 内反转 A 和 B。
【讨论】: