Matlab Structures Check for Duplicates

Here’s a really useful function that I wrote to detect if a given structure already exists within a list of structures. The gist of the function is that it converts structs to cell matrices of strings and uses the beautiful ismember() function (the version acting on cells of strings) to determine if the “entity” exists within the list of “entities.”

This function works for any string-based struct which is great for reuse! It *might* also work for numeric-array members.

function B = isDuplicate(entity, entities)
% Purpose:  Determines if the passed entity is a duplicate in the list of
%           entities passed.
% Precond:  entity: any structure
%           entities: cell matrix of structures
% Returns:  True if the entity is a duplicate. False otherwise.
    B = false;
 
    % If the list is empty, then there's nothing to check
    if(isempty(entities) || isempty(entities{1})) return; end
    % Convert entity from a structure to a column cell matrix of strings
    E = struct2cell(entity);
    % Convert entity list from cell matrix of structures to cells of strings
    ECL = cellfun(@struct2cell, entities, "UniformOutput", false);
 
    for k = 1:numel(ECL)
        % Get the current cell of strings
        ec = ECL{k};
        % The number of strings matching between the two cells
        numMatches = sum(ismember(E, ec));
        % If the entire entity matches, we have a duplicate!
        isDup = numMatches == numel(E);
        if(~isDup) continue; end
 
        % We won't print a detailed msg since we don't 
        % know the structure of entity.
        fprintf("%s\n", "Duplicate not accepted!");
        B = true;
        return;           
    end
end

Example Walkthrough

Assume the following:

entity = struct("fname", "joel", "lname", "kemp");
entities = {struct("fname", "bob", "lname", "saget")  struct("fname", "joel", "lname", "kemp")};

Then the transformation of entity from a struct to a cell matrix (using struct2cell()) yields:
{'joel' ; 'kemp'}

The transformation of the matrix of structures, entities (using cellfun() and struct2cell() to each cell of entities) yields a 1×2 cell matrix:
{ {'bob' ; 'saget'} {'joel' ; 'kemp'} }

The first iteration over the 1×2 cell matrix grabs the first 2×1 inner-cell:
{'bob' ; 'saget'}

Using ismember(), we compare the two cells:
{'joel' ; 'kemp'} and {'bob' ; 'saget'}

This comparison yields 1′s where the elements of the first cell matrix are equal the second cell matrix. Ultimately, the result is [0 ; 0], since ‘joel’ is not equal to ‘bob’ and ‘kemp’ is also not equal to ‘saget’.

The second comparison that takes place is between the cells:
{'joel' ; 'kemp'} and {'joel' ; 'kemp'}

The ismember() function acts yet again and yields a result matrix: [1 ; 1] since the first names and last names clearly match.

A duplicate is such that all parts of “entity” are found in a structure within the list of entities. To verify that all of the parts have been matched, I use the fact that “entity” had two parts. In addition, the sum of the elements of the results matrix [1 ; 1] will yield the total number of matching parts for the last comparison that we did; this is the number 2.

Since the sum of the result matrix is equal to the total number of parts for the structure, “entity,” all of the parts must have matched. Thus, we have a duplicate.

Happy coding!

Comments

comments