MATLAB中eval函数的正确使用或规避:数组运算适配问题
解决MATLAB中元胞数组布尔测试的适配问题
你遇到的核心问题是:用eval拼接字符串的方式没法处理元胞数组里的向量/数组,因为把数组转成字符串后,拼接出来的表达式不符合MATLAB的向量运算语法。而且你不想用switch逐个处理运算符,那咱们可以用更优雅的函数句柄方案,完全避开switch和不安全的eval。
方法一:预定义运算符-函数句柄映射(兼容所有MATLAB版本)
这种方法最安全高效,把每个运算符对应到一个能处理数组的函数句柄:
% 先建立运算符到对应测试函数的映射 opHandler = containers.Map(... {'<=', '>=', '==', '<', '>', '~='}, ... {@(x) x <= 0, @(x) x >= 0, @(x) x == 0, @(x) x < 0, @(x) x > 0, @(x) x ~= 0}... ); % 你的原始数据 a{1} = [1 2 3 4]; a{2} = [5 1 4 6]; typeTest{1} = '<='; typeTest{2} = '<'; % 用cellfun批量处理,直接调用对应函数句柄 result = cellfun(@(arr, op) opHandler{op}(arr), a, typeTest, 'UniformOutput', false);
运行后result里就会存储每个数组的测试结果:比如result{1}是[false false false false],result{2}是[false false false false](因为你的测试值都是正数,和0比的话结果都是false)。
方法二:动态生成函数句柄(MATLAB R2021b+适用)
如果你的MATLAB版本比较新(R2021b及以后),可以用str2func动态生成运算符对应的函数句柄,不用预先定义所有映射,更灵活:
% 定义通用测试函数,动态生成运算符的函数句柄 funCheck = @(arr, op) str2func(['@(x) x ', op, ' 0'])(arr); % 原始数据 a{1} = [1 2 3 4]; a{2} = [5 1 4 6]; typeTest{1} = '<='; typeTest{2} = '<'; % 调用cellfun,注意设置'UniformOutput'为false,因为结果是数组 result = cellfun(funCheck, a, typeTest, 'UniformOutput', false);
为什么原来的eval方法不行?
原来的funCheck=@(x,y)eval([num2str(x),y,'0'])会把数组x转成空格分隔的字符串(比如[1 2 3 4]变成'1 2 3 4'),拼接后得到'1 2 3 4<=0'——这在MATLAB里是语法错误,因为不能直接让多个数值和0做比较。而上面的方法都是直接对整个数组做元素-wise的布尔运算,完全符合MATLAB的向量运算逻辑。
另外提醒一句:尽量避免用eval,它不仅容易出语法问题,还有安全风险(如果运算符字符串被篡改),而且性能比函数句柄差很多。
内容的提问来源于stack exchange,提问作者Guuk
相关产品推荐
相关产品推荐

