正确使用eval或在MATLAB中避免使用它

时间:2018-05-10 18:05:03

标签: matlab eval

在我的代码中,我使用特定的方式来定义测试函数:在单元格中,存储了布尔类型的测试('< =','> =','=='...)。之后我想对特定值应用测试。我存储测试类型的原因是我的代码特有的,允许我编写代码而不需要事先了解测试类型。另一种方法是使用例如switch来指定每个布尔测试的测试,但是我想避免它的那一刻。

MWE

a{1}=[1 2 3 4];
a{2}=[5 1 4 6];

typeTest{1}='<=';
typeTest{2}='<';

%create function
funCheck=@(x,y)eval([num2str(x),y,'0']);

%works
funCheck(1,'<')

%apply on cell (does not work due to the array in a)
cellfun(funCheck,a,typeTest)

使用此语法,无法同时使用eval和向量表达式...

1 个答案:

答案 0 :(得分:3)

现在在MATLAB中避免使用eval实际上非常简单。如果你将typeTest定义为一组函数句柄而不是字符串,那么你就是99%:

a{1}=[1 2 3 4];
a{2}=[5 1 4 6];

typeTest{1}=@le; % <=
typeTest{2}=@lt; % <

%create function
funCheck=@(x,y)y(x,0);

%works
funCheck(1,typeTest{1})

%apply on cell
cellfun(funCheck,a,typeTest,'UniformOutput',false)

请注意,我在'UniformOutput',false的参数中添加了cellfun。这将创建一个单元格数组作为输出,其中每个单元格是a中其中一个元素和typeTest中相应元素的结果。也就是说,TypeTest{1}检查{1},a{2}检查TypeTest{2}

我实际上会创建一个包含所有实际测试的数组,如下所示:

checks = { @(x)x<=3 , @(x)x>4 };

现在您对运算符和右操作数进行编码。这使您可以灵活地创建其他类型的支票:@(x)var(x)<1e-3@(x)max(diff(x))<1等。

要将每个检查应用于每个数据阵列,您需要使用bsxfun。我尝试了以下语句,但它在Octave 3.0.0中无法正常工作(我认为这可能是一个错误):

bsxfun( @(fun,data){fun{1}(data{1})}, checks(:)', a(:) )

这将生成一个2x2(检查次数的数据数组)单元格数组。

上述有效的替代方案是:

cellfun( @(fun,data)fun(data), ...
         repmat(checks(:)',numel(a),1), ...
         repmat(a(:),1,numel(checks)), ...
         'UniformOutput',false)