matlabmatlab-struct

find string in non-scalar structure matlab


Here's a non-scalar structure in matlab:

clearvars s
s=struct;
for id=1:3
s(id).wa='nko';
s(id).test='5';
s(id).ad(1,1).treasurehunt='asdf'
s(id).ad(1,2).treasurehunt='as df'
s(id).ad(1,3).treasurehunt='foobar'
s(id).ad(2,1).treasurehunt='trea'
s(id).ad(2,2).treasurehunt='foo bar'
s(id).ad(2,3).treasurehunt='treasure'
s(id).ad(id,4).a=magic(5);
end

is there an easy way to test if the structure s contains the string 'treasure' without having to loop through every field (e.g. doing a 'grep' through the actual content of the variable)?

The aim is to see 'quick and dirtily' whether a string exists (regardless of where) in the structure. In other words (for Linux users): I'd like to use 'grep' on a matlab variable.

I tried arrayfun(@(x) any(strcmp(x, 'treasure')), s) with no success, output:

ans =

  1×3 logical array

   0   0   0

Solution

  • One general approach (applicable to any structure array s) is to convert your structure array to a cell array using struct2cell, test if the contents of any of the cells are equal to the string 'treasure', and recursively repeat the above for any cells that contain structures. This can be done in a while loop that stops if either the string is found or there are no structures left to recurse through. Here's the solution implemented as a function:

    function found = string_hunt(s, str)
      c = reshape(struct2cell(s), [], 1);
      found = any(cellfun(@(v) isequal(v, str), c));
      index = cellfun(@isstruct, c);
      while ~found && any(index)
        c = cellfun(@(v) {reshape(struct2cell(v), [], 1)}, c(index));
        c = vertcat(c{:});
        found = any(cellfun(@(c) isequal(c, str), c));
        index = cellfun(@isstruct, c);
      end
    end
    

    And using your sample structure s:

    >> string_hunt(s, 'treasure')
    
    ans =
    
      logical
    
       1        % True!