4

I have a matlab struct which several levels (e.g. a.b(j).c(i).d). I would like to write a function which gives me the fields I want. If the struct has only one level, it would be easy:

function x = test(struct, label1)
  x = struct.(label1)
end

E.g. if I have the struct a.b I could get b via: test('b'). However, this does not work with subfields, if I have a struct a.b.c I can't use test('b.c') to access it.

Is there any way to pass a string with the full field name (with dots) to a function to retrieve this field? Or is there even a better way to get only the fields that I select through the function arguments?

The goal? Sure, it would be a useless function for one fieldname, but I wan't to pass a list of fieldnames as argument to receive exactly these fields.

2 Answers 2

2

You should use subsref function:

function x = test(strct, label1)
F=regexp(label1, '\.', 'split');
F(2:2:2*end)=F;
F(1:2:end)={'.'};
x=subsref(strct, substruct(F{:}));
end

To access a.b.c you can use:

subsref(a, substruct('.', 'b', '.', 'c'));

The test function first splits the input using .as a delimiter and creates a cell array F where every other element is filled with . and then its elements are passed to substruct as arguments.

Note that if there are arrays of structs involved it will get the first one. For a.b(i).c(j).d passing b.c.d will return a.b(1).c(1).d. See this question for the way it should be handled.

As a side note, I renamed your input variable struct to strct because struct is a built-in MATLAB command.

Sign up to request clarification or add additional context in comments.

1 Comment

Sorry for being absent so long, this solution works great for me, thanks a lot!
1

One way is to create a self calling function to do this:

a.b.c.d.e.f.g = 'abc'
value = getSubField ( a, 'b.c.d.e.f.g' )

  'abc'

function output = getSubField ( myStruct, fpath )
  % convert the provided path to a cell
  if ~iscell(fpath); fpath = strread ( fpath, '%s', 'delimiter', '.' ); end
  % extract the field (should really check if it exists)
  output = myStruct.(fpath{1});
  % remove the one we just found
  fpath(1) = [];
  % if fpath still has items in it -> self call to get the value
  if isstruct ( output ) && ~isempty(fpath)
    % Pass in the sub field and the remaining fpath
    output = getSubField ( output, fpath );
  end
end

1 Comment

Thank you, it does work, but the other solution looks more clear to me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.