如何优雅地忽略 MATLAB 函数的某些返回值
Posted
技术标签:
【中文标题】如何优雅地忽略 MATLAB 函数的某些返回值【英文标题】:How to elegantly ignore some return values of a MATLAB function 【发布时间】:2010-10-19 08:06:57 【问题描述】:是否可以从函数中获取“第 n 个”返回值,而不必为之前的所有 n-1
返回值创建虚拟变量?
假设我在 MATLAB 中有以下函数:
function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
现在假设,我只对 third 返回值感兴趣。这可以通过创建一个虚拟变量来完成:
[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
但我认为这有点丑。我认为您可能可以执行以下操作之一,但您不能:
[_, _, variableThatIWillUse, _] = func;
[, , variableThatIWillUse, ] = func;
variableThatIWillUse = func(3);
variableThatIWillUse = func()(3);
是否有任何优雅的方法可以做到这一点?
到目前为止,最好的解决方案是简单地将variableThatIWillUse
用作虚拟变量。这使我不必创建一个真正的虚拟变量来污染工作空间(或者我需要清除)。简而言之:解决方案是对每个返回值使用variableThatIWillUse
,直到有趣的返回值。之后的返回值可以简单地忽略:
[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
我仍然认为这是非常丑陋的代码。
【问题讨论】:
除了使用我在回答中描述的单元格数组之外,重复变量名可能是您唯一的其他解决方案。希望你的变量名没有“variableThatIWillUse”那么长。 =) 其实他们是。 'dummy' 只是一个例子。通常我会使用'variableThatIWillNotUse'。其他变量名为“variableThatIMightUse”、“variableThatIWillUse2”和“variableThatCanBarelyFitOnA80CharacterLine”。我正在研究长名字和凶杀等级之间的相关性。 ;) 实际上,由于 R2009b 忽略函数返回,使用 '~'-Char 可以更优雅地解决。例如:[~,b] = sort(rand(10,1)) 致新读者:^ 应该是正确答案。请参阅下面的ManWithSleeve's answer 在你的例子中,如果你只想要第三个输出参数,你应该使用:[ variableThatIWillUse,variableThatIWillUse,variableThatIWillUse] = func;无需清除虚拟变量。对于较新的 MATLAB 版本 >=R2009b,请使用 [~,~,variableThatIWillUse] = func; 【参考方案1】:我写了第k个输出函数:
function kth = kthout(k, ffnc, varargin)
% kthout: take the kth varargout from a func call %FOLDUP
%
% kth = kthout(k, ffnc, varargin)
%
% input:
% k which varargout to get
% ffnc function to call;
% varargin passed to ffnc;
% output:
% kth the kth argout;
[outargs1:k] = feval(ffnc, varargin:);
kth = outargsk;
end %function
然后你可以调用
val_i_want = kthout(3, @myfunc, func_input_1, func_input_2);
你也可以像这样封装函数:
func_i_want = @(varargin)(kthout(3, @myfunc,varargin:)); % Assuming you want the third output.
之后使用
val_i_want = func_i_want(func_input_1, func_input_2);
请注意,使用这样的匿名函数会产生开销,这不是我在代码中会被调用数千次的事情。
【讨论】:
【参考方案2】:没有任何理由不使用 ans(n)。像这样:
a = rand([5 10 20 40]);
size(a);
b = ans(2);
它给出 b = 10,这种方式将与所有 MATLAB 版本兼容。
此外,当您不知道会有多少参数时,这可以获取第二个输出参数!然而,如果你这样做:
[~, b] = size(a);
那么 b = 8000! (您需要以~
结尾,以获取更多参数!)
【讨论】:
这个答案假设返回的变量是一个向量,这可能不是 OP 的意思。 这毫无意义。size(a)
和 [b,c]=size(a)
返回不同的东西。 MATLAB 中的函数会根据输出参数的数量改变行为。
我很难理解这个答案。我不知道这对这里答案的质量有何贡献,更不用说这不能直接回答原始问题。
6年后,我不再使用Matlab了。据我记得,函数“size()”是无关紧要的——我只是将它用作一个返回多个参数的函数。关键是我可以简单地调用 func() 然后调用 ans(n) 来获取返回的变量号 n 的值。这似乎适用于某些情况并且向后兼容。当然,它可能只适用于某些函数,或者变量类型,无论如何。 6 年后我能提供的帮助就这么多了。【参考方案3】:
如果您希望使用一种将变量留在位桶中的样式,那么一个合理的替代方案是
[ans, ans, variableThatIWillUse] = myfun(inputs);
ans
当然是 MATLAB 的默认垃圾变量,在会话过程中经常被覆盖。
虽然我确实喜欢 MATLAB 现在允许的新技巧,使用 ~
指定忽略的返回变量,但这是向后兼容性的问题,因为旧版本的用户将无法使用您的代码。
在至少发布几个 MATLAB 版本之前,我通常会避免使用类似的新东西,以确保只有很少的用户会陷入困境。例如,即使现在我发现人们仍在使用足够旧的 MATLAB 版本,他们无法使用匿名函数。
【讨论】:
是的,它很聪明,但是如果你给 ans 变量赋值,原生的 Matlab 编辑器会给出警告。我不认为有警告是非常优雅的...... 您可以关闭警告。以这个注释字符串结束行 %#ok Mlint 将忽略它。没有警告。【参考方案4】:在 MATLAB 2010a 中,我找到了一种满足您要求的简洁方法。
只是简单地使用字符“~”(当然不带引号)作为你的虚拟变量(返回多个参数时,你想要多少就多少)。如果函数旨在处理丢失的数据,这也适用于函数的输入参数。
不知道以前的版本有没有,最近才发现。
【讨论】:
没看到之前的回答吗? 在之前的两个答案中都有介绍。【参考方案5】:这有点像 hack,但它确实有效:
首先是一个简单的示例函数:
Func3 = @() deal(1,2,3);
[a,b,c]=Func3();
% yields a=1, b=2, c=3
现在这里的关键是,如果您在多表达式赋值的左侧使用两次变量,则较早的赋值会被后面的赋值破坏:
[b,b,c]=Func3();
% yields b=2, c=3
[c,c,c]=Func3();
% yields c=3
(只是为了检查,我还验证了此技术适用于 [mu,mu,mu]=polyfit(x,y,n)
,如果您只关心 polyfit
的第三个参数。)
有更好的方法;请参阅ManWithSleeve's answer。
【讨论】:
没想到这样解决。然而,我觉得这个解决方案牺牲了意图的清晰性来换取聪明。 我个人只是使用 [junk, junk, c] = function_call() 并假设“垃圾”从来都不是一个重要的变量,如果它包含大量内存,我会在必要时清除它. 致反对者:为什么是-1?这个答案是在 R2009b 甚至发布之前写的,所以@ManWithSleeve 的答案在当时是行不通的。现在,当然,这是正确的方法。 也许您答案第一行的评论会有所帮助?我刚通过google来到这里,看来值得更新。 The MathWorks 没有正式保证从左到右的赋值,因此您可能不应该依赖在 [c,c,c] = myFunc() 之后使用 c。 (请参阅此处的评论 #26:blogs.mathworks.com/loren/2009/09/11/…)【参考方案6】:使用 MATLAB 版本 7.9 (R2009b),您可以使用 ~,例如,
[~, ~, variableThatIWillUse] = myFunction();
请注意,,
不是可选的。只输入[~ ~ var]
将不起作用,并且会引发错误。
详情请参阅release notes。
【讨论】:
有点恼人的是它不是“_”。 (我想那已经被拍了?) @SamB: 虽然在don't care
中使用not
运算符也不是那么糟糕
请注意,
不是可选的。仅仅输入[~ ~ var]
将不起作用,并且会引发错误。
我会说这是“正确”的答案。另一个只是解决不存在的问题的技巧。虽然没有双关语......
这个问题是在 R2009b 之前的 2009 年提出的,当时 ~ 不起作用。【参考方案7】:
这是您可以使用的另一个选项。首先制作一个元胞数组来捕获所有输出(您可以使用NARGOUT 函数来确定给定函数返回多少输出):
a = cell(1,3); % For capturing 3 outputs
% OR...
a = cell(1,nargout(@func)); % For capturing all outputs from "func"
然后调用函数如下:
[a:] = func();
然后只需从 a 中删除您想要的元素,然后覆盖 a:
a = a3; % Get the third output
【讨论】:
【参考方案8】:您可以创建一个只返回选定输出的函数(或匿名函数),例如
select = @(a,b) a(b);
然后你可以这样调用你的函数:
select(func,2);
select(func,1:3);
或者您可以将输出分配给变量:
output(1,2:4) = select(func,1:3);
【讨论】:
对我不起作用。试过decimatedfftx = select(fft(x,12),1:4:12);
select(func,2)
呼叫func(2)
。我没有看到它选择输出参数的位置。以上是关于如何优雅地忽略 MATLAB 函数的某些返回值的主要内容,如果未能解决你的问题,请参考以下文章