【问题标题】:Intersection indices by rows按行的交叉点索引
【发布时间】:2013-01-07 20:17:52
【问题描述】:

鉴于这两个矩阵:

m1 = [ 1 1;
       2 2;
       3 3;
       4 4;
       5 5 ];

m2 = [ 4 2;
       1 1;
       4 4;
       7 5 ];

我在找一个函数,比如:

indices = GetIntersectionIndecies (m1,m2);

其输出将是

indices = 
          1
          0
          0
          1
          0

如何在不使用循环的情况下找到这两个矩阵之间行的交集索引

【问题讨论】:

    标签: matlab matrix indexing intersection vectorization


    【解决方案1】:

    一种可能的解决方案:

    function [Index] = GetIntersectionIndicies(m1, m2)
    [~, I1] = intersect(m1, m2, 'rows');
    Index = zeros(size(m1, 1), 1);
    Index(I1) = 1;
    

    顺便说一句,我喜欢 @Shai 的创造性解决方案,如果你的矩阵很小,它比我的解决方案快得多。但是,如果您的矩阵很大,那么我的解决方案将占主导地位。这是因为如果我们设置T = size(m1, 1),那么@Shai 的答案中的tmp 变量将是T*T,即如果T 很大,则一个非常大的矩阵。下面是一些快速测试的代码:

    %# Set parameters
    T = 1000;
    M = 10;
    
    %# Build test matrices
    m1 = randi(5, T, 2);
    m2 = randi(5, T, 2);
    
    %# My solution
    tic
    for m = 1:M
    [~, I1] = intersect(m1, m2, 'rows');
    Index = zeros(size(m1, 1), 1);
    Index(I1) = 1;
    end
    toc
    
    %# @Shai solution
    tic
    for m = 1:M
    tmp = bsxfun( @eq, permute( m1, [ 1 3 2 ] ), permute( m2, [ 3 1 2 ] ) );
    tmp = all( tmp, 3 ); % tmp(i,j) is true iff m1(i,:) == m2(j,:)
    imdices = any( tmp, 2 );
    end
    toc
    

    设置T = 10M = 1000,我们得到:

    Elapsed time is 0.404726 seconds. %# My solution
    Elapsed time is 0.017669 seconds. %# @Shai solution
    

    但是设置T = 1000M = 100 我们得到:

    Elapsed time is 0.068831 seconds. %# My solution
    Elapsed time is 0.508370 seconds. %# @Shai solution
    

    【讨论】:

    • 废话。刚刚也输入了这个...+1
    • @SamehKamal 我刚刚更新了我的答案以包括速度测试,展示了我的解决方案相对于 Shai 的解决方案将证明是最佳的情况。
    • 不,你是对的,当我编写代码时,我使用了 [~,I1,~]=intersect(m1,m2,...) ,但是在你的原始代码中,你使用了 intersect(m2,m1,...) 所以输出的正确位置是 [~,~,I1]...我的错因为没有注意到这一点。除此之外,我希望这些答案总是来得如此之快,并在 SO...
    • @natan 实际上,直到我看到您的评论后,我才意识到我应该在代码中切换 m1m2,然后我可以完全消除对第三个输出的考虑,所以谢谢你:-)
    【解决方案2】:

    bsxfun怎么样

    function indices = GetIntersectionIndecies( m1, m2 )
        tmp = bsxfun( @eq, permute( m1, [ 1 3 2 ] ), permute( m2, [ 3 1 2 ] ) );
        tmp = all( tmp, 3 ); % tmp(i,j) is true iff m1(i,:) == m2(j,:)
        indices = any( tmp, 2 );
    end
    

    干杯!

    【讨论】:

    • 拜托,你能把你的代码写成function indecis = GetIntersectionIndecies(m1,m2)的形式
    • 多么迷人的解决方案! +1
    • 我刚刚做了一个快速的速度测试,如果size(m1, 1) 很小,你的解决方案效果很好,但是随着矩阵大小的增加,tmp 变得非常大。但仍然是一个非常有创意的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    相关资源
    最近更新 更多