kgk
kgk

Reputation: 659

Count items in one array in another array matlab

Given the values in C, I want to count how many times I encounter each of these values in the vector B. For example, if C = [1 2], I'd like to count how many "1"s are in B and how many "2"s are in B by checking the elements of array C.

However, the code I have seems to count up to 5, but what the true output should be is that the number of 1s is 2 and the number of 2s is 3.

The code I wrote is shown below. Any help would be certainly appreciated.

My code :

 B = [ 1 2 1 4 5 2 2 ]
 C = [ 1 2 ]

 lb = length(B)
 lc = length(C)

for i = 1:length(B)
    for j = 1:length(C)
      if B(1,i)==C(1,j)
          c=c+1
          A(i)=c
      end 
    end
end

Upvotes: 1

Views: 285

Answers (2)

rayryeng
rayryeng

Reputation: 104565

Santhan Salai gave the corrected answer if you want to stick with loops. However, for efficiency, you could achieve what you want with bsxfun and sum if you don't want to loop:

>> B = [ 1 2 1 4 5 2 2 ];
>> C = [ 1 2 ];
>> D = sum(bsxfun(@eq, B, C.'), 2)

D =

     2
     3

bsxfun is a nice tool that allows you to broadcast data across singleton dimensions. In our case, I used the equals functions to check for element-wise equality and I transposed C so that it becomes a column vector. What will be produced is a matrix where we have as many rows as there are in C and as many columns as there are in B. Each row of this output matrix tells you which elements were equal to each corresponding element in C. C is broadcasted such that we get a matrix of a bunch of [1;2] columns mashed together for as many elements as there are in B and B is broadcasted such that we get replicates of B with as many rows as there are in C. By doing element-wise equality, we would produce a logical matrix where each element for a row tells you which elements were equal to the corresponding value of C. All you have to do now is sum over the columns to get how many elements were equal to each value in C, hence the sum call over the second dimension.


If you want overkill, you can also use accumarray. Assuming that B and C only consist of integers, do:

>> B = [ 1 2 1 4 5 2 2 ];
>> C = [ 1 2 ];
>> D = accumarray(B.', 1);    

D =

     2
     3
     0
     1
     1

This however computes the frequency of all unique values in B, and so you'd just want the first two entries in D.


One more alternative is to use histc:

>> B = [ 1 2 1 4 5 2 2 ];
>> C = [ 1 2 ];
>> D = histc(B, C)

D =

   2     3

What you are basically computing is a histogram of B at specified bins, which are denoted at C.

Upvotes: 3

Santhan Salai
Santhan Salai

Reputation: 3898

Using arrayfun could be one alternate to your loop

out = arrayfun(@(x) sum(ismember(B,x)), C)

Here is your corrected loop

count = zeros(1,numel(C));
for ii = 1:numel(C)
    for jj = 1:numel(B)
        if (C(ii) == B(jj))
            count(ii) = count(ii) + 1;
        end
    end
end

Upvotes: 1

Related Questions