2

我有一个迭代和随机修剪一个巨大的整数向量的过程,我想找出每次迭代之间删除了哪些元素。这个向量有很多重复,使用 ismember() 和 setdiff() 对我没有多大帮助。

作为说明,如果 X = [1,10,8,5,10,3,5,2]:

step 0: X = 1,10,8,5,10,3,5,2
step 1: X = 1,10,8,10,3,5,2 (5 is removed)
step 2: X = 1,10,8,3,2 (10 and 5 are removed)
step 3: X = 10,8,3,2 (1 is removed)
step 4: X = 2 (10, 8 and 3 are removed)
step 5: X = [] (2 is finally removed)

我的目标是找到在每个步骤中删除的元素(即 5 然后,10 和 5 等等)。我可能会hist(X, unique(X))在步骤之间找到一个过于复杂的解决方案,但我认为 matlab 中存在一个更优雅(更便宜!)的解决方案。

4

2 回答 2

3

我想出了通过减去两者并迭代不同的值来从输出中恢复输入的想法,然后这些值就是被删除元素的索引。

% Input.
X = [1, 10, 8, 5, 10, 3, 5, 2];

% Remove indices for the given example.
y = { [4], [4 6], [1], [1 2 3], [1] };

% Simulate removing.
for k = 1:numel(y)

  % Remove elements.
  temp = X;
  temp(y{k}) = [];

  % Determine number of removed elements.
  nRemoved = numel(X) - numel(temp);

  % Find removed elements by recovering input from output.
  recover = temp;
  removed = zeros(1, nRemoved);
  for l = 1:nRemoved
    tempdiff = X - [recover zeros(1, nRemoved - l + 1)];
    idx = find(tempdiff, 1);
    removed(l) = X(idx);
    recover = [recover(1:idx-1) X(idx) recover(idx:end)];
  end

  % Simple, stupid output.
  disp('Input:');
  disp(X);
  disp('');
  disp('Output:');
  disp(temp);
  disp('');
  disp('Removed elements:');
  disp(removed);
  disp('');
  disp('------------------------------');

  % Reset input.
  X = temp;

end

给定示例的输出:

Input:
    1   10    8    5   10    3    5    2

Output:
    1   10    8   10    3    5    2

Removed elements:
 5

------------------------------
Input:
    1   10    8   10    3    5    2

Output:
    1   10    8    3    2

Removed elements:
   10    5

------------------------------
Input:
    1   10    8    3    2

Output:
   10    8    3    2

Removed elements:
 1

------------------------------
Input:
   10    8    3    2

Output:
 2

Removed elements:
   10    8    3

------------------------------
Input:
 2

Output:
[](1x0)

Removed elements:
 2

------------------------------

这是一个合适的解决方案,还是我错过了一些(明显的)低效率?

于 2019-03-13T06:47:22.063 回答
2
  1. 这种方法是内存密集型的。它使用隐式扩展N计算大小为x的中间矩阵,M其中N是 的元素数XM是 的唯一元素数。这可能可行或不可行,具体取决于您的典型和.XNM

    X = [1,10,8,5,10,3,5,2];
    Y = [8,10,2,1]; % removed 10, 5, 5, 3. Order in Y is arbitrary
    u = unique(X(:).');
    removed = repelem(u, sum(X(:)==u,1)-sum(Y(:)==u,1));
    

    removed =
         3     5     5    10
    

    对于 R2016b 之前的 Matlab 版本,您需要bsxfun而不是隐式扩展:

    removed = repelem(u, sum(bsxfun(@eq,X(:),u),1)-sum(bsxfun(@eq,Y(:),u),1));
    
  2. 如果 中的值X始终为正整数,则可以使用更有效sparse的方法,用于计算每个元素出现的次数:

    X = [1,10,8,5,10,3,5,2];
    Y = [8,10,2,1]; % removed 10, 5, 5, 3. Order in Y is arbitrary
    removed = repelem(1:max(X), sparse(1,X,1) - sparse(1,Y,1));
    
于 2019-03-12T18:34:18.900 回答