【问题标题】:Issue a warning in case a struct with dynamic fields contains a NaN value如果具有动态字段的结构包含 NaN 值,则发出警告
【发布时间】:2019-03-13 22:02:19
【问题描述】:

我有一个包含测量数据参数集的结构。有时数据集不完整,缺少的一些参数会设置为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})))

【问题讨论】:

  • 它是否包含double NaNchar 'NaN'?我只是想确保这不是一个错字...
  • 对不起!我的错!双楠不是字符'NaN'

标签: matlab dynamic struct warnings nan


【解决方案1】:

您可以获取结构 (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) 

我还想提出一种完全不同的方法 - objects!如果你定义了一个带有特定字段的类,你可以设置它们的default values and validation functions。如果你不熟悉面向对象编程(OOP)的话题,可以先阅读this

【讨论】:

    【解决方案2】:

    1) 假设 struct 字段包含 doublechararraycellarray 或嵌套 struct 的值,如果 NaN 是,则以下递归函数返回逻辑 truedouble 或字符串'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) 假设警告应该由 value 'NaN' 作为字符串 发出,如问题中最初所述:

    if(nnz(strcmp(struct2cell(Parameter), 'NaN')))
        disp('Warning! Parameter set not complete!');
    end
    

    【讨论】:

    • 你得到我的投票,因为这是最接近 OP 想要的。尽管struct2array 可能会出现问题,如果结构可以包含除数字以外的任何内容(例如另一个struct)...
    【解决方案3】:

    您可以使用函数fieldnames 来获取结构的字段名称。

    获得字段列表后,您可以扫描它们并检查它们的值

    你可以设置一个计数器,如果它大于0,你至少知道一个字段是无效的。

    您也可以保存无效字段的索引并列出这些字段的名称。

    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
    

    【讨论】:

    • 啊...我忽略了,我的结构中还有另一个结构。于是就有了 Parameter.Info.Valve 和 Parameter.Info.Armature
    猜你喜欢
    • 2013-01-19
    • 2012-09-27
    • 2016-12-13
    • 1970-01-01
    • 2019-01-10
    • 2014-09-05
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多