【问题标题】:check if variable exists in the workspace with cellfun使用 cellfun 检查工作区中是否存在变量
【发布时间】:2013-01-23 14:26:19
【问题描述】:

考虑以下示例:

dat1 = 1;
dat2 = 2;

Variables = {'dat1','dat2'};

a = cellfun(@(x)exist(x,'var'),Variables);

for i = 1:length(Variables);
    a2(i) = exist(Variables{i},'var');
end

为什么“a”和“a2”返回不同的值,即为什么使用 cellfun 没有说明变量存在于工作区中?我错过了什么?

【问题讨论】:

  • 哇,真的很奇怪。我已经检查了函数表达式(使用@):1. 可以访问环境中的变量-并且- 2. 保留正确的参数类型。两者都是真的,这真的很奇怪。在我看来,您刚刚在cellfunexist 中发现了错误!恭喜:)
  • @Kate:你缺少的是每个匿名函数都有自己的工作区(也花了我一段时间)。请参阅下面的答案。

标签: matlab exists


【解决方案1】:

好的,我想我明白这里发生了什么:

当您调用匿名函数时,它会创建自己的工作区,就像任何普通函数一样。但是,这个新工作区将无法访问调用方工作区。

这样

funH = @(x)exist(x,'var')

如果您提供 'x' 作为输入 (funH('x')),则只会返回 1,因为它的整个工作区由变量 'x' 组成。

因此,

funH = @(x)exist('x','var') 

无论您提供什么作为输入,都将始终返回 1。

有两种可能的方法:

(1) 使用evalin 在调用者的工作区进行评估

 funH =  @(x)evalin('caller',sprintf('exist(''%s'',''var'')',x))

(2) 使用whos 的输出,并检查现有变量列表

 Variables = {'dat1','dat2'};
 allVariables = whos;
 a3 = ismember(Variables,{allVariables.name})

【讨论】:

  • 我有点困惑。如果新工作区无权访问调用者工作区,那么此代码 b = 3; feval(@(x) b+x, 2) 如何返回 5?请解释一下好吗?
  • @zplesivcak:在将b 添加到匿名函数的定义中时,您将其副本添加到匿名函数的工作区。如果在定义匿名函数后改变b的值,匿名函数内部的b不会改变。
【解决方案2】:

我认为您应该将cellfun 行写为:

a = cellfun(@(x) exist('x','var'),Variables); 

使其等同于 for 循环。 另请参阅如何在 Matlab's Documentation 示例中使用 exist...

编辑:

在(我想我)理解 Jonas 的回答之后,无论是 dat1=1 还是 dat1=[],上面的行都将始终返回 true。为了使用cellfun,请参阅 Jonas 的回答...

【讨论】:

  • 我错了。无论输入如何,您的函数都将始终返回 true。
  • 从 cellfun 上的示例中,它没有显示 x 应该放在引号之间。 Cpositives = cellfun(@(x) x(x>0), C, 'UniformOutput',false) 所以我觉得不是这样。
猜你喜欢
  • 2014-09-08
  • 2011-03-12
  • 2014-06-23
  • 2017-02-13
  • 2011-12-19
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多