Выдает предупреждение, если структура с динамическими полями содержит значение NaN - PullRequest
0 голосов
/ 09 октября 2018

У меня есть структура, содержащая набор параметров данных измерений.Иногда набор данных не является полным, и некоторые параметры, которые отсутствуют, будут установлены на NaN.

Теперь я хочу отобразить предупреждение, если где-нибудь есть хотя бы один (или более) NaNв наборе параметров.

Например:

Parameter.mass=1;
Parameter.volume=2;
Parameter.force=NaN;

Проблема в том, что не каждый набор параметров имеет одинаковые поля.

Поэтому я ищу что-то вроде:

if isnan(Parameter.*) >= 1
  display('Warning! Parameter set not complete!')
end

Поскольку я упустил из виду, что в моей структуре есть и другая структура ...

Так что есть также

Parameter.Info.Valve
Parameter.Info.Armature

, которая вызывает ошибкуиспользуя код il_raffa [...]

if(isnan(Struct.(st_fields{i})))

Ответы [ 3 ]

0 голосов
/ 09 октября 2018

Вы можете получить поля структуры (fieldnames), а затем перебрать их.Это также можно вызывать рекурсивно, если у вас есть вложенные структуры, как показано в примере ниже:

function checkNaNFields(testedStruct, containerName)
if nargin < 2
  containerName = {inputname(1)};
end
fn = fieldnames(testedStruct);
for indFN = 1:numel(fn)
  field = testedStruct.(fn{indFN});
  if isstruct(field)
    % If the field is a struct, call recursively:
    checkNaNFields( field, [containerName, fn{indFN}] );
  elseif isnumeric(field) && isnan(field)
    warning(['Field "' strjoin([containerName, fn{indFN}],'.') '" contains a NaN value!']);  
  end
end

>> Parameter = struct('mass', 1, 'volume', 2, 'force', NaN, 'info', struct('value', NaN) );
>> checkNaNFields(Parameter);

Warning: Field "Parameter.force" contains a NaN value! 
> In checkNaNFields (line 12) 
Warning: Field "Parameter.info.value" contains a NaN value! 
> In checkNaNFields (line 12)
  In checkNaNFields (line 10) 

Я также хотел бы предложить совершенно другой подход - объекты !Если вы определяете класс с определенными полями, вы можете установить их значения по умолчанию и функции проверки .Если вы не знакомы с темой объектно-ориентированного программирования (ООП), вы можете начать с чтения this .

0 голосов
/ 09 октября 2018

1) Предполагая, что поля структуры содержат значения как double, chararray, cellarray или вложенные struct, следующая рекурсивная функция возвращает логическое true, если найдено NaNлибо в виде double, либо в виде строки 'NaN':

function hasNaN = STRUCT_hasNaN(s)
    if(iscell(s)), c = s; else, c = struct2cell(s); end
    i = cellfun(@isnumeric, c);
    j = cellfun(@ischar, c);
    k = cellfun(@isstruct, c) | cellfun(@iscell, c);
    hasNaN = nnz(cellfun(@isnan, c(i))) || nnz(strcmpi(c(j), 'nan')) || nnz(cellfun(@STRUCT_hasNaN, c(k)));
end

, которую можно использовать как:

if(STRUCT_hasNaN(Parameter))
    disp('Warning! Parameter set not complete!');
end

2) Предполагая, что все поля содержат значения как двойные, и предупреждение должно быть выдано как минимум значением NaN:

if(nnz(isnan(struct2array(Parameter))))
    disp('Warning! Parameter set not complete!');
end

3) Предполагается, что предупреждение должно быть выдано значением NaN в виде строки ,как изначально указано в вопросе:

if(nnz(strcmp(struct2cell(Parameter), 'NaN')))
    disp('Warning! Parameter set not complete!');
end
0 голосов
/ 09 октября 2018

Вы можете использовать функцию fieldnames для получения имен полей структуры.

Получив список полей, вы можете отсканировать их и проверить их значения

Вы можете установить счетчик, и если он больше 0, вы знаете, что по крайней мере поле недопустимо.

Вы также можете сохранить недопустимый индекс поля foud и перечислить имена таких полей..

Parameter.mass=1;
Parameter.volume=2;
Parameter.force=NaN

st_fields=fieldnames(Parameter)

cnt=0
for i=1:length(st_fields)
   if(strcmp(Parameter.(st_fields{i}),'NaN'))
      cnt=cnt+1
      idx(cnt)=i
   elseif(isnan(Parameter.(st_fields{i})))
      cnt=cnt+1
      idx(cnt)=i
   end
end
if(cnt > 0)
   disp('Warning! Parameter set not complete!')
   disp('The following Fields are unvalid:')
   for i=1:cnt
      st_fields{idx(i)}
   end
end
...