动态创建结构数组而不使用eval

时间:2014-03-09 04:48:15

标签: arrays matlab struct structure eval

我正在尝试在Matlab中运行时创建一个结构数组。

    A= {'dark';'oa_45'; 'oa_225'};

    for i = 1:3
      tmp =load([folder '/' A{i} '.txt']);
      eval([A{i} '.count=tmp(:,1:2)']);
      eval([A{i} '.mean=mean(tmp(:,1:2),1)']);
      eval([A{i} '.sqrtmean=sqrt(' A{i} '.mean)']);
      eval([A{i} '.stdev=std(tmp(:,1:2),1)']);
      eval(A{i});
    end

因为我知道,使用eval这是一个相当糟糕的做法,我想知道是否有一种简单的方法可以避免eval

我认为可以在循环之前创建结构数组,然后只用括号表示法分配循环中的子字段:

   s.(A{i}).count = ...

我在这里发现了一些建议,说subsasgn似乎有可能。这似乎比eval函数复杂得多。

有人知道避免eval功能的简单方法,还是只是最好的调用? 我只是出于好奇,我想对于这三个向量,性能的损失并不重要。

最诚挚的问候, MECHANIX

2 个答案:

答案 0 :(得分:2)

假设您可以使用一个结构来保存名为“dark”,“oa_45”,“oa_225”和“sqrtmean”字段的三个结构,这样你可能会尝试这个 -

代码版本1(推荐)

A= {'dark';'oa_45'; 'oa_225'};
fieldnames1 = {'count';'mean';'stdev'};
funcnames1 = {'';'mean';'std'};

for k = 1:numel(A)
    tmp =load([folder '/' A{k} '.txt']);
    struct1 = A{k};
    for i = 1:numel(fieldnames1)
        if isempty(funcnames1{i})
            comp_struct.(struct1).count=tmp(:,1:2);
        else
            fh = str2func(funcnames1{i});
            comp_struct.(struct1).(fieldnames1{i}) = fh(tmp(:,1:2),1);
        end
    end
    comp_struct.(struct1).sqrtmean = sqrt(comp_struct.(struct1).mean);
end

因此,'comp_struct.dark'将是你原来的'黑暗'等等。

更进一步,删除IF-ELSE -

代码版本2(强烈推荐)

A= {'dark';'oa_45'; 'oa_225'};
fieldnames1 = {'count';'mean';'stdev'};
funcnames1 = {'donothing';'mean';'std'};

for k = 1:numel(A)
    tmp =load([folder '/' A{k} '.txt']);
    struct1 = A{k};
    for i = 1:numel(fieldnames1)
        fh = str2func(funcnames1{i});
        comp_struct.(struct1).(fieldnames1{i}) = fh(tmp(:,1:2),1);
    end
    comp_struct.(struct1).sqrtmean = sqrt(comp_struct.(struct1).mean);
end

不要忘记在路径中添加此功能 -

function out = donothing(varargin)
out = varargin{1};

如果嵌套循环困扰​​你或你不想进入函数句柄而你只是想用代码行占用相同空间的东西替换EVAL,请使用以下内容,但是我虽然不会推荐一般情况 -

代码版本3(不推荐)

A= {'dark';'oa_45'; 'oa_225'};
for k = 1:numel(A)
    tmp =load([folder '/' A{k} '.txt']);
    comp_struct.(A{k}).count = tmp(:,1:2);
    comp_struct.(A{k}).mean = mean(tmp(:,1:2),1);
    comp_struct.(A{k}).sqrtmean = sqrt(comp_struct.(A{k}).mean);
    comp_struct.(A{k}).stdev = std(tmp(:,1:2),1);
end

答案 1 :(得分:0)

但是你没有创建“结构数组”,你创建了3个独立的结构变量!实际的结构数组将是非常优选的:

A = {'dark';'oa_45'; 'oa_225'};

% Preallocation is obviously optional, but good practice
% A cell array initialiser will make structarray the same size
structarray = struct('name',A,'count',[],'mean',[],'sqrtmean',[],'stdev',[]);

for i = 1:length(A)
  tmp = load([folder '/' A{i} '.txt']);
  % structarray(i).name = A{i};   % if we didn't preallocate
  structarray(i).count = tmp(:,1:2);
  structarray(i).mean = mean(tmp(:,1:2),1);
  structarray(i).sqrtmean = sqrt(structarray(i).mean);
  structarray(i).stdev = std(tmp(:,1:2),1);
end

Avoiding eval通常会涉及相当多的重组,但在几乎所有情况下,您最终得到的代码都更强大,更易于使用。

例如,当您从基本工作区中的命令行和简单脚本开始时,依赖于特定命名的变量就很好 - 对于用户来说是有意义的,以便跟踪什么是什么。一旦你进展到更大的问题,你会发现它真的不能很好地扩展,你需要以一种有意义的方式做事 - 当你在函数之间传递数据时无论如何变得无关紧要。那就是像单元格数组和结构数组这样的工具真正发挥作用的时候。结构特别方便,因为你几乎总是可以用额外的字段来识别事物,就像我上面的name一样。