如何优雅地忽略 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 函数的某些返回值的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB 中忽略 NaN 的累积行值的平均计算

忽略python多重返回值

如何在 MATLAB 中将函数作为输出值返回?

如何优雅处理多参数返回/无参数返回——std::optional

matlab一组数据里面最小值,有没有函数可以直接找出来?

如何编写返回多种数据类型值的Java函数?