matlab 查找两个向量之间的多个重合

jk9hmnmh  于 2022-11-15  发布在  Matlab
关注(0)|答案(2)|浏览(199)

我有两个向量,我正在尝试在一定的容差范围内找出一个在另一个上的所有重合,而不是使用for循环。容差的意思是,例如,如果我有数字3,容差为2,我希望将值保持在3±2内,因此(1,2,3,4,5)。

A = [5 3 4 2]; B = [2 4 4 4 6 8];

我想要获得一个单元数组,每个单元上包含容差为1(或更多)个单元的所有重合的数目。(A=B+-1)我有一个有零单位的解(A=B),它看起来像这样:

tol = 0;
[tf, ia] = ismembertol(B,A,tol,'DataScale',1); % For tol = 0, this is equivalent to using ismember
idx = 1:numel(B);
ib = accumarray(nonzeros(ia), idx(tf), [], @(x){x}) % This gives the cell array

输出为:

ib = 
[]
[]
[2 3 4]
[1]

这就是我们想要的。如果我将公差更改为1,代码将不会按预期工作。相反,它会输出:

tol = 1
[tf, ia] = ismembertol(B,A,tol,'DataScale',1); % For tolerance = 1, this is equivalent to using ismember
idx = 1:numel(B);
ib = accumarray(nonzeros(ia), idx(tf), [], @(x){x}) % This gives the cell array
ib = 
[5]
[2 3 4]
[]
[1]

当我期望获得以下信息时:

ib = 
[2 3 4 5]
[1 2 3 4]
[2 3 4]
[1]

我做错了什么?有没有其他解决方案?

ubof19bj

ubof19bj1#

您的问题是,在代码的当前状态下,ismembertol只为在A中找到的B的每个元素输出一个索引,因此当一个元素在容差范围内被多次找到时,您会丢失信息。
根据文档,您可以使用'OutputAllIndices',true值对参数语法,只需调用ismembertol即可在ia中输出所需内容:

A = [5 3 4 2]; B = [2 4 4 4 6 8];

tol = 0;
[tf, ia] = ismembertol(A,B,tol,'DataScale',1,'OutputAllIndices',true);

celldisp(ia) % tol = 0

ia{1} =

 0

ia{2} =

 0

ia{3} =

 2
 3
 4

ia{4} =

 1

celldisp(ia) % tol = 1

ia{1} =

 2
 3
 4
 5

ia{2} =

 1
 2
 3
 4

ia{3} =

 2
 3
 4

ia{4} =

 1
yeotifhr

yeotifhr2#

这里是一种手动方法,只是为了提供另一种方法。它计算所有绝对差异的中间矩阵(使用隐式展开),并根据小于公差的条目的行和列索引构建结果:

A = [5 3 4 2];
B = [2 4 4 4 6 8];
tol = 1;
[ii, jj] = find(abs(A(:).'-B(:))<=tol);
ib = accumarray(jj, ii, [numel(A) 1], @(x){x});

请注意,此方法

  • 可能是内存密集型,因为中间矩阵;
  • 由于不使用ismembertol,所以可以在老版本的MatLab中使用,但隐式扩展需要显式调用bsxfun
[ii, jj] = find(abs(bsxfun(@minus, A(:).', B(:)))<=tol);
ib = accumarray(jj, ii, [numel(A) 1], @(x){x});

相关问题