Search code examples
matlabindexingcell-array

How to collect the final score by going through each column names?


I have a cell array that has points and names

Points     NameList1        NameList2
[20]        'Mat'            'Ken'
[15]        'Ken'            'John'
[10]        'Mario'          'Mat'
[5]         'John'           'Harry'
[0]         'Kelly'          'Mario'

I would like to collect the points that everyone collected. I was planning on using the unique function to get the names and going to each column to see how many points everyone collected and storing it (example: 'Mat' [20,10]. The problem is I have no idea how to go through every column and collect the number.

Thank you.


Solution

  • This is another classic case of accumarray. accumarray works by using a bunch of keys and a bunch of values. For those keys that are the same, the corresponding values get mapped to the same bin and the default behaviour of accumarray is to add up those values that get mapped to the same bin. In your case, the keys would be the names and the values are the points.

    What I would do is concatenate all of those names over all of the columns in your cell array into a single column vector, then create points vector that is duplicated for as many columns as we have names. After, we can use unique to determine the list of all unique names (first output) and get a unique ID for each name that we see in the large list of names (third output). From there, we can accumulate our points:

    scores = {[20]        'Mat'            'Ken'
    [15]        'Ken'            'John'
    [10]        'Mario'          'Mat'
    [5]         'John'           'Harry'
    [0]         'Kelly'          'Mario'};
    
    points = cell2mat(scores(:,1)); %// Get points and duplicate
    points = repmat(points, size(scores,2)-1, 1);
    
    %// Create list of all names
    names = scores(:,2:end);
    
    %// Find unique names and unique ID numbers
    [unique_names, ~, id] = unique(names(:));
    
    %// Calculate score
    out = accumarray(id, points);
    

    out will contain the scores for all players and unique_names will contain the names of all the people you're tallying the scores with.

    Therefore, displaying both variables, we get:

    >> unique_names
    
    unique_names = 
    
        'Harry'
        'John'
        'Kelly'
        'Ken'
        'Mario'
        'Mat'
    
    >> out
    
    out =
    
         5
        20
         0
        35
        10
        30
    

    As such, Harry got 5 points, John got 20 points, and so on.