In a struct, how can you extract values for a vector of fieldnames

Hello,
I have a struct called MyStruct. I can extract the field names with the command
MyFieldNames = fieldnames(MyStruct);
If I'm interested in extracting the values for first n of MyFieldNames, is there a way I can do this using the "getfield" command? If I try
Temp = getfield(StateSpace, MyFieldNames(1:n))
or
Temp = Temp = getfield(StateSpace, MyFieldNames)
I get an error saying, "Index exceeds matrix dimensions."
Thank you, Kevin

3 commentaires

What do you mean by the first field?
For example, if MyStruct has 10 fields, and I was only interested in the first 3 of fields. MyFieldNames(1:3) would produce the field names associated with the first 3 fields. Is there a way to extract the values for the first 3 fields?
If it wasn't clear what I was asking, for example, assume 'x1' is one of the field names.
The command getfield(StateSpace,'x1') works fine and produces the desired result, but if I want to return values for multiple field names, is there a way to do this? Or do I have to extract the values one at a time using a for loop?

Connectez-vous pour commenter.

 Réponse acceptée

Kevin Bachovchin
Kevin Bachovchin le 22 Fév 2013
MyFieldNames = fieldnames(MyStruct);
for i=1:3
MyValues(i,1) = getfield(MyStruct,MyFieldNames{i});
end

Plus de réponses (4)

Kevin's answer can be condensed to oneline of code using cellfun
cellfun(@(x)(MyStruct.(x)),fieldnames(MyStruct))
You could even make this into an anonymous function fieldvalues
fieldvalues = @(MyStruct)(cellfun(@(fieldName)(MyStruct.(fieldName)),fieldnames(MyStruct)))
You could use a dedicated function like:
function Value = GetFields(S, Name)
if ischar(Name)
try
Value = S.(Name);
catch
Value = []; % Or an error message
end
elseif iscellstr(Name)
Value = cell(size(Name));
for iName = 1:numel(Name)
try
Value{iName} = S.(Name{iName});
catch
% Nothing or an error message?!
end
end
else
error('Input type not handled')
end
For large numbers of fieldnames is this more efficient:
function Value = GetFields(S, Name)
[dummy, iName, iS] = intersect(Name, fieldnames(S));
Value = cell(size(Name));
Data = struct2cell(S);
Value(iName) = Data(iS);

1 commentaire

It's much easier to just use a for loop. It's weird that MATLAB only allows the getfield command to take a single field as an argument, but that problem can be overcome by using a for loop.

Connectez-vous pour commenter.

Azzi Abdelmalek
Azzi Abdelmalek le 22 Fév 2013
Modifié(e) : Azzi Abdelmalek le 22 Fév 2013
Edit
if a is your struct array
s=fieldnames(a)
out=a
rmfield(out,s(4:end)) % will remove fields from 4 to the end

11 commentaires

If it wasn't clear what I was asking, for example, assume 'x1' is one of the field names.
The command getfield(StateSpace,'x1') works fine and produces the desired result, but if I want to return values for multiple field names, is there a way to do this? Or do I have to extract the values one at a time using a for loop?
Azzi Abdelmalek
Azzi Abdelmalek le 22 Fév 2013
Modifié(e) : Azzi Abdelmalek le 22 Fév 2013
Look at edited answer
I'd prefer to get a 1x3 matrix for values in fields 1 to 3. Is there a way to do that all at once rather than extracting the values one at a time in a for loop like shown below?
MyFieldNames = fieldnames(MyStruct);
for i=1:3
MyValues(i,1) = getfield(MyStruct,MyFieldNames{i});
end
I am not following you. Have you tried the edited answer?
s=fieldnames(a)
out=a
rmfield(out,s(4:end)) % will remove fields from 4 to the end
Once you get your three fields in the variable out use
result=reshape(cell2mat(struct2cell(out)),3,[])
Yes, I did. Your code produces a 1x1 struct with 3 fields as the answer. I'm looking to obtain a 1x3 for the values only, which is what my code using the for loop does. If there's no simpler way of doing that besides the for loop, that's fine I guess. I just would have thought MATLAB would have some built-in way of extracting values for more than 1 field at a time.
s=fieldnames(a)
out=a
out=rmfield(out,s(4:end))
result=reshape(cell2mat(struct2cell(out)),3,[])
The last line produces an error for me. "Error using cell2mat (line 53) Cannot support cell arrays containing cell arrays or objects."
I think I'm just going to stick with extracting the values using the for loop unless there is some way to use the "getfield" command with multiple fields at a time.
Look at this example
out=struct('v',{4},'y',{6},'z',{45})
result=reshape(cell2mat(struct2cell(out)),3,[])
For your structure, I don't get an error, but for the structure I'm using, I do. Maybe it's because for my structure the values of the fields are 1x1 syms.
result=struct2cell(out)

Connectez-vous pour commenter.

There's just such an assymetry here. You have this great little function fieldnames() that accepts a struct and returns a cell array of names Where's the complementary fieldvalues() that accepts a struct and returns all struct values?
struct2cell() works great, but this question has been asked over & over for many years
Guess I'm writing my own.... just because: :)
function values = fieldvalues(struc)
% values = fieldvalues(struc)
%
% DESCRIPTION:
% Extracts all values from a struct and returns them as a Kx1 cell array,
% mirroring the functionality of MATLAB's fieldnames(struc)
%
%
% SEE ALSO:
% fieldnames(struc) Complementary function to fieldvalues
assert( isstruct(struc), sprintf("\n\nfieldvalues(struc)\n\tArgument 'struc' must be a structure\n\n"));
values = struct2cell(struc);
end

Catégories

En savoir plus sur Data Type Identification dans Centre d'aide et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by