Finding NaN values in Structure

47 ビュー (過去 30 日間)
Christian Baetz
Christian Baetz 2017 年 1 月 11 日
コメント済み: Christian Baetz 2017 年 1 月 19 日
Hi all,
I have the following code for finding a NaN value in a structure:
structure.w.c = 5;
structure.w.d = 4;
structure.x.a = 1;
structure.y.a = NaN;
structure.z.a = 3;
first_level = fieldnames(structure);
structure_path_first = strcat('structure.',first_level);
structure_path_complete = {};
for i=1:1:length(first_level)
temp = eval(structure_path_first{i});
second_level{i} = fieldnames(temp);
if strcmp(second_level{1,i},'a')
structure_path_complete{i} = strcat(structure_path_first{i},'.',second_level{i});
temp_2 = eval(char(structure_path_complete{i}));
if isnan(temp_2)
value_nan{i} = structure_path_complete{i};
end
end
end
The problem of the structure is that I do not know the names of the second level (w,x,y,z) and also not the number of array fields (a,d,c) in advance.
The code is working fine and I get the complete names of the array fields containing a NaN. The question now is, is there a smarter way than using for-loops finding these fields?
Thank you for your answers.
Cheers
Christian

採用された回答

Guillaume
Guillaume 2017 年 1 月 11 日
As others have said, do not use eval, particularly as there's a much easier way to convert a variable into a field name.
The way I would approach this is with a recursive function, avoiding hardcoding multiple loops. If the field being tested is a structure call yourself again:
function fnames = findnanfields(s)
%s: a scalar structure
%fnames: column cell array of field names that are nan. recurses through structures
fnames = {};
for fn = fieldnames(s)'
fieldcontent = s.(fn{1});
if isstruct(fieldcontent)
subfields = findnanfields(fieldcontent);
if ~isempty(subfields)
fnames = [fnames; strcat(fn{1}, '.', subfields)];
end
elseif isnan(fieldcontent)
fnames = [fnames; fn{1}];
end
end
end
This works regardless of the number of levels, number of fields, etc. However, it assumes that each field is scalar (as your code did).
Note that instead of returning the field hierarchy as a dotted string it may be better to return it as a cell array, depending on what you're planning to do with that information. In which case, replace the name generation by:
fnames = cellfun(@(sn) [fn{1}, sn], subfields, 'UniformOutput', false);
%instead of fnames = [fnames; strcat(fn{1}, '.', subfields)];
  1 件のコメント
Christian Baetz
Christian Baetz 2017 年 1 月 19 日
Thanks for this answer. The function is working fine. I assumed MATLAB provides a function to find such NaN-fields.

サインインしてコメントする。

その他の回答 (1 件)

Alexandra Harkai
Alexandra Harkai 2017 年 1 月 11 日
It is good practice to avoid eval:
first_level = fieldnames(structure);
counter = 0; % keep track of the found NaNs so far
for i = first_level' % row vector of field names
temp = structure.(char(i));
second_level = fieldnames(temp);
for j = second_level' % row vector of field names
if isnan( structure.(char(i)).(char(j)) )
counter = counter + 1;
value_nan{counter} = [ 'structure.', char(i), '.', char(j) ];
end
end
end
Alternatively, you can use arrayfun to loop through the field names:
value_nan = {}; % init as empty
function addPath(first, second) % function to register the path
if isnan(structure.(char(first)).(char(second)))
value_nan = [value_nan; ['structure.', char(first), '.', char(second)]]; % append new line
end
end
arrayfun(@(first) arrayfun(@(second) addPath(first, second), fieldnames(structure.(char(first)))'), fieldnames(structure)'); % run through all first and second fields

カテゴリ

Help Center および File ExchangeStructures についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by