【问题标题】:Given two arrays A and B, how to get B values which are the closest to A给定两个数组A和B,如何获得最接近A的B值
【发布时间】:2016-12-26 14:20:08
【问题描述】:

假设我有两个按升序排列的数组,即:

A = [1 5 7],B = [1 2 3 6 9 10]

我想从 B 创建一个新向量 B',它只包含最接近 A 值的值(每个值一个)。

我还需要索引。所以,在我的例子中,我想得到:

B' = [1 6 9],Idx = [1 4 5]

请注意,第三个值是 9。确实 6 更接近 7,但它已经被“采用”,因为它接近 4。

有合适的代码的想法吗?

注意:我的真实数组要大得多,并且包含实数(不是 int)值

另外,假设 B 比 A 长

谢谢!

【问题讨论】:

标签: arrays matlab sorting


【解决方案1】:

假设你想最小化A的元素和B的匹配元素之间的整体差异,这个问题可以写成分配给每一行(@的元素987654324@) 给定成本矩阵C 的列(B 的元素)。匈牙利(或 Munkres')算法解决了分配问题。

我假设你想最小化 AB 中匹配元素之间的累积平方距离,并使用来自 https://www.mathworks.com/matlabcentral/fileexchange/20652-hungarian-algorithm-for-linear-assignment-problems--v2-3- 的 Yi Cao 的函数 [assignment,cost] = munkres(costMat)

A = [1 5 7];
B = [1 2 3 6 9 10];
[Bprime,matches] = matching(A,B)

function [Bprime,matches] = matching(A,B)
    C = (repmat(A',1,length(B)) - repmat(B,length(A),1)).^2;
    [matches,~] = munkres(C);
    Bprime = B(matches);
end

假设您想递归查找匹配项,正如您的问题所建议的那样,您可以遍历 A,对于 A 中的每个元素,在 B 中找到最接近的剩余元素并丢弃它(sortedmatching 下面);或者您可以迭代地形成并丢弃AB 中剩余元素之间的距离最小化匹配,直到A 中的所有元素都匹配(greedymatching):

A = [1 5 7];
B = [1 2 3 6 9 10];
[~,~,Bprime,matches] = sortedmatching(A,B,[],[])
[~,~,Bprime,matches] = greedymatching(A,B,[],[])

function [A,B,Bprime,matches] = sortedmatching(A,B,Bprime,matches)
    [~,ix] = min((A(1) - B).^2);
    matches = [matches ix];
    Bprime = [Bprime B(ix)];
    A = A(2:end);
    B(ix) = Inf;
    if(not(isempty(A)))
        [A,B,Bprime,matches] = sortedmatching(A,B,Bprime,matches);
    end
end

function [A,B,Bprime,matches] = greedymatching(A,B,Bprime,matches)
    C = (repmat(A',1,length(B)) - repmat(B,length(A),1)).^2;
    [minrows,ixrows] = min(C);
    [~,ixcol] = min(minrows);
    ixrow = ixrows(ixcol);
    matches(ixrow) = ixcol;
    Bprime(ixrow) = B(ixcol);
    A(ixrow) = -Inf;
    B(ixcol) = Inf;
    if(max(A) > -Inf)
        [A,B,Bprime,matches] = greedymatching(A,B,Bprime,matches);
    end
end

虽然在您的示例中产生相同的结果,但所有三种方法都可能对相同的数据给出不同的答案。

【讨论】:

    【解决方案2】:

    通常我会在 Matlab 中的 forwhile 循环中尖叫,但在这种情况下,我看不到如何对解决方案进行矢量化。至少它是 O(N)(或足够接近,取决于在 B 中有多少与每个 A(i) 同等接近的匹配)。在 C 中编写以下代码并将其编译为 mex 文件会非常简单,以使其以最佳速度运行,但这里有一个纯 Matlab 解决方案:

    function [out, ind] = greedy_nearest(A, B)
    
    if nargin < 1, A = [1 5 7]; end
    if nargin < 2, B = [1 2 3 6 9 10]; end
    
    ind = A * 0;
    walk = 1;
    for i = 1:numel(A)
        match = 0;
        lastDelta = inf;
        while walk < numel(B)
            delta = abs(B(walk) - A(i));
            if delta < lastDelta, match = walk; end
            if delta > lastDelta, break, end
            lastDelta = delta;
            walk = walk + 1;
        end
        ind(i) = match;
        walk = match + 1;
    end
    out = B(ind);
    

    【讨论】:

      【解决方案3】:

      您可以先获取 A 中的每个值到 B 中的每个值的绝对距离,对它们进行排序,然后在向下查看每一列时获取序列的第一个唯一值。

      % Get distance from each value in A to each value in B
      [~, minIdx] = sort(abs(bsxfun(@minus, A,B.')));
      
      % Get first unique sequence looking down each column
      idx = zeros(size(A));
      for iCol = 1:numel(A)
          for iRow = 1:iCol
              if ~ismember(idx, minIdx(iRow,iCol))
                  idx(iCol) = minIdx(iRow,iCol);
                  break
              end
          end
      end
      

      idx 应用到B 时的结果

      >> idx
      1     4     5
      >> B(idx)
      1     6     9
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多