Search code examples
arraysmatlabuniqueaccumarray

How to quickly get the array of multiplicities


What is the fastest way of taking an array A and outputing both unique(A) [i.e. the set of unique array elements of A] as well as the multiplicity array which takes in its i-th place the i-th multiplicity of the i-th entry of unique(A) in A.

That's a mouthful, so here's an example. Given A=[1 1 3 1 4 5 3], I want:

  1. unique(A)=[1 3 4 5]
  2. mult = [3 2 1 1]

This can be done with a tedious for loop, but would like to know if there is a way to exploit the array nature of MATLAB.


Solution

  • uA = unique(A);
    mult = histc(A,uA);
    

    Alternatively:

    uA = unique(A);
    mult = sum(bsxfun(@eq, uA(:).', A(:)));
    

    Benchmarking

    N = 100;
    A = randi(N,1,2*N); %// size 1 x 2*N
    
    %// Luis Mendo, first approach
    tic
    for iter = 1:1e3;
        uA = unique(A);
        mult = histc(A,uA);
    end
    toc
    
    %// Luis Mendo, second approach    
    tic
    for iter = 1:1e3;
        uA = unique(A);
        mult = sum(bsxfun(@eq, uA(:).', A(:)));
    end
    toc
    
    %'// chappjc
    tic
    for iter = 1:1e3;
        [uA,~,ic] = unique(A);    % uA(ic) == A
        mult= accumarray(ic.',1);
    end
    toc
    

    Results with N = 100:

    Elapsed time is 0.096206 seconds.
    Elapsed time is 0.235686 seconds.
    Elapsed time is 0.154150 seconds.
    

    Results with N = 1000:

    Elapsed time is 0.481456 seconds.
    Elapsed time is 4.534572 seconds.
    Elapsed time is 0.550606 seconds.