3

I have an array of 100K structs. I am listing below the contents of one such struct:

Iteration:1

BlockID:86

The BlockID can have values between 1 and 100. I want to find out the count of occurrences of BlockID. For eg.: BlockID "1" occurred 25 times; BlockID "98" occurred 58 times and so on.

I looked online and tried the options mentioned in these links, but could not get a solution: Matlab: Count number of structs that have a specific content how to count unique elements of a cell in matlab? Matlab: How to calculate how many unique strings are stored in the cell?

Community
  • 1
  • 1
Sarvavyapi
  • 810
  • 3
  • 23
  • 35

3 Answers3

1

You can use arrayfun and count_unique (count_unique is not an official function - it's from the matlab central file exchange and can be found here):

ids= arrayfun(@(x)x.BlockID, struct1);
[vals, counts] = count_unique(ids);

NB: As pointed out by rody_o (though he/she missed the fact that the indexing is unnecessary) there is an alternative way to concatenate the, ids, namely

ids = [struct1.BlockID];

Alternatively you could create your own count_unique function if you wished,

function [counts, uns] = count_unique(ids)
uns= unique(ids);
counts = arrayfun(@(x)sum(ids == x), uns);
jmetz
  • 12,144
  • 3
  • 30
  • 41
  • Thanks, this worked. I was using arrayfun, but was not able to proceed further to the point of getting the unique values. I added just one extra step to what you have mentioned. Converted "ids" to a matrix using cell2mat and then the rest was the same. Thanks again. – Sarvavyapi Aug 02 '12 at 21:24
  • @Sarvavyapi: Could you explain again why you needed cell2mat? The output of `arrayfun` is an array... – jmetz Aug 02 '12 at 21:33
  • I am not sure why, but I got this error when I gave "unique(ids)": Error using cell/unique (line 45) Input must be a cell array of strings. Thats why I tried cell2mat. – Sarvavyapi Aug 03 '12 at 02:39
  • @Sarvavyapi: weird - there _is_ a unique that works on cell arrays, but also one for normal arrays... could you confirm that `ids` is an array? – jmetz Aug 03 '12 at 17:35
1

For the sake of simplicity,suppose there is a struct array of size 10 with BlockID which value between '1' and '3':

%generate the struct array
for n = 1:10 
    structs(n).BlockID = num2str(randi(3));
end
%structs.BlockID : 3     2     1     3     3     2     1     1     2     2

To find out the count of occurrences of BlockID:

count = accumarray(str2double({structs.BlockID})',1);
%count : 3     4     3

Now count(i) is the count of occurrences of BlockID of value 'i'.

Sorry for my poor English.

Eastsun
  • 18,526
  • 6
  • 57
  • 81
1

You can simply use Matlab's own indexing techniques, in combination with hist and unique:

% sample data

a(1).BlockID   = 68
a(1).iteration = 1

a(2).BlockID   = 88
a(2).iteration = 12

a(3).BlockID   = 88
a(3).iteration = 14

a(4).BlockID   = 16
a(4).iteration = 18

% collect all BlockID values into array
b = [a.BlockID];

% count unique entries
[occurrences, entries] = hist(b, unique(b))

Output:

occurrences =
    1     1     2
entries =
    16    68    88

I always find it surprising that something as widely applicable as the [struct(indices).member] notation is known (or used) by so few developers...

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
  • Tip: You don't need to index when concatenating - the notation you mention is even simpler: `[a.member]` and is of course only universally applicable specific member types ;) – jmetz Aug 03 '12 at 17:45
  • True, I forgot it is a habit of mine to write it consistently with structs you *do* need to index... – Rody Oldenhuis Aug 03 '12 at 21:59
  • thanks everyone for your responses. I will try out the options and give the results here. – Sarvavyapi Aug 06 '12 at 19:41