【问题标题】:how to find the first element that has been seen twice in a vector如何找到向量中出现两次的第一个元素
【发布时间】:2014-08-20 17:46:39
【问题描述】:

我想找到出现在向量中先前位置的第一个元素。

例如,如果向量是:

v = [1, 3, 2, 3, 4, 5];

答案是v(4) = 3,因为 3 是第一个出现两次的元素。
有没有办法向量化这个操作?

更新:
这是我目前的解决方案,您有更好的建议吗?

[s o] = sort(v);  % sort the array
d = diff(s);      % the first zero corresponds to the first repetitive element  
d = find(d == 0);  

o(d(1) + 1) 是出现两次的第一个元素的索引。

新更新:
遵循@mwengler 的解决方案,我现在提出解决方案来找到 MATRIX 每一行的第一个重复元素。

function vdup = firstDup(M)
    [SM Ord] = sort(M, 2);    % sort by row
    [rows cols] = find(~diff(SM, 1, 2));   % diff each row, and find indices of the repeated elements in sorted rows
    Mask = (size(M,2) + 1) * ones(size(M)); % create a Mask matrix with all size(M,2)+1
    ind = sub2ind(size(Ord), rows, cols+1); % add 1 to the column indices
    Mask(ind) = Ord(ind);   % get the original indices of each repeated elements in each row
    vdup = min(Mask, [], 2); % get the minimum indices of each row, which is the indices of first repeated element

【问题讨论】:

  • 在您更新的解决方案中,我会指出对于 v = [1 3 4 4 3 5] 您会得到答案 5,因为代码不会返回重复的 first ,它返回最小的重复(因为排序)

标签: matlab duplicates vectorization


【解决方案1】:

这会奏效。 @Steve 指出了您更新的解决方案中的一个错误。

[~, ~, Iv] = unique(v, 'stable');
idx = find(diff(Iv)-1, 1)+1;
el = v(idx);

此后,el 将包含v 中的第一个重复元素,idx 将成为其在v 中的索引。

首先您使用stable unique 来查找唯一元素。第二个输出参数包含每个唯一元素的原始索引。然后运行diff(Iv) - 1 来查找原始索引中的跳跃。您使用find(, 1) 获取第一个元素并添加一个以获取原始向量中的索引。索引原始向量以获取所需的元素。

【讨论】:

  • +1 虽然我认为你应该把它分成两个步骤,因为 OP 也有兴趣获取索引和值:idx = find(diff(Iv)-1, 1)+1 然后el = v(idx)
  • 对于旧版 MATLAB(R2012a 中引入了'stable' 选项),请使用[~,Iv] = unique(v, 'first'); Iv = sort(Iv); 而不是第一行。看到这个question
  • 谢谢!有没有办法对矩阵 M 进行类似的操作?我想获取每行的第一个重复元素。
  • 是的,试试unique(A, 'rows', 'stable')(或者如果您使用的是@Amro 建议的旧版本的MATLAB,则首先不要使用稳定版)
  • 这个边界情况还是有一点小错误:说v = [ 1 1 1], Iv=1, diff(Iv)=[],那么你的代码就不行了。稍作修改即可,只需使用第 3 个返回的参数替换第 2 个参数 Iv。
【解决方案2】:

@Fash 最初提出的答案几乎可行。走得更远:

sv = sort(v);
repeated = sv(~diff(sv));
ifr = find(ismember(v,repeated),'first');
ir2 = find(v==v(ifr));
index_desired = ir2(2);
value_desired = v(index_desired);

【讨论】:

  • 非常感谢!你的回答几乎有效。再往下走,即使返回 MATRIX 每一行的第一个重复元素,我也能得到解决方案!请参阅我更新的问题。
【解决方案3】:
idx = find(any(triu(bsxfun(@eq, v, v.'), 1)), 1);
el = v(idx);

这是如何工作的:bsxfun(...)v 的每个条目相互比较。 triu(...,1) 仅保留与 previous 元素的匹配项(仅保留对角线以上的值)。 any 告诉哪些条目与之前的某个条目匹配。 find(...,1) 给出第一个此类条目的索引。

【讨论】:

    【解决方案4】:

    存储在一个哈希表中,您可以检查它是否已经有内容?

    类似:

    If (hash.hasValue(i))
      return true;
    else
      hash.insert(i, 1);
      return false;
    

    其中 i 是键,位置,并且可以只包含一些简单的东西,例如允许较小的结构大小。

    【讨论】:

    • 与 Java、C++ 等一般编程语言不同,我认为在 matlab 中哈希会很慢
    • 不是真的,MATLAB 使用 Java,所以它会像 Java 本身一样慢/快。这不是这不是最好的方法的原因。
    • 安萨里,出于好奇,你能向我解释一下未来吗?
    猜你喜欢
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-27
    相关资源
    最近更新 更多