如何优雅地忽略MATLAB函数的某些返回值?


120

是否可以从函数中获取“ nth”个返回值,而不必n-1在此之前为所有返回值创建伪变量?

假设我在MATLAB中具有以下功能:

function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;

现在假设,我只对第三个返回值感兴趣。这可以通过创建一个虚拟变量来实现:

[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;

但是我认为这有点丑陋。我认为您可能可以执行以下操作之一,但不能:

[_, _, variableThatIWillUse, _] = func;

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

是否有任何优雅的方式来做到这一点做的工作?


到目前为止,最好的解决方案是简单地将variableThatIWillUse用作虚拟变量。这使我不必创建一个真正的伪变量,该变量会污染工作空间(或者我需要清除)。简而言之:解决方案是variableThatIWillUse对每个返回值使用直到有趣的值。之后的返回值可以简单地忽略:

[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;

我仍然认为这是非常丑陋的代码,但是如果没有更好的方法,那么我想我会接受答案。


除了使用我在答案中描述的单元格数组之外,重复变量名可能是您唯一的其他解决方案。希望您的变量名不如“ variableThatIWillUse”长。=)
gnovice

其实他们是。“虚拟”只是一个例子。通常我会使用'variableThatIWillNotUse'。其他变量名为“ variableThatIMightUse”,“ variableThatIWillUse2”和“ variableThatCanBarelyFitOnA80CharacterLine”。我正在研究长名与凶杀等级之间的关系。;)
Jordi

26
实际上,由于R2009b忽略函数返回可以使用'〜'-Char更好地解决。例如:[〜,b] = sort(rand(10,1))
ymihere

1
对于新读者:^应该是正确的答案。请参阅下面的ManWithSleeve的答案
A.Wan 2015年

1
在您的示例中,如果只希望使用第三个输出参数,则应使用:[variableThatIWillUse,variableThatIWillUse,variableThatIWillUse] = func; 无需清除虚拟变量。对于> = R2009b的较新MATLAB版本,请使用[〜,〜,variableThatIWillUse] = func;。
蒂埃里·达隆

Answers:


38

这有点像骇客,但它可以工作:

首先是一个简单的示例函数:

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的答案


7
没想到要像这样解决它。但是,我觉得这种解决方案牺牲了对聪明的意图的明确性。
Jukka Dahlbom,09年

5
我个人只是使​​用[junk,junk,c] = function_call()并假设“ junk”从来都不是重要变量,并且如果它包含大量内存,我将在必要时清除它。
杰森S

5
对下降投票者:为什么为-1?这个答案是在R2009b发行之前编写的,因此@ManWithSleeve的答案当时无法使用。现在,当然,这是正确的方法。
詹森·S

2
在答案的第一行中添加注释可能会有所帮助?我只是通过Google来到这里的,所以似乎值得更新。
FvD

MathWorks并未正式保证从左到右的赋值,因此在[c,c,c] = myFunc()之后,您可能不应该依赖使用c。(请参阅此处的评论#26:blogs.mathworks.com/loren/2009/09/11/…
马特·克劳斯

226

在MATLAB版本7.9(R2009b)中,您可以使用〜,例如,

[~, ~, variableThatIWillUse] = myFunction();

请注意,,不是可选的。仅输入[~ ~ var]将不起作用,并会引发错误。

有关详细信息,请参见发行说明


3
有点烦人的不是“ _”。(我想那是已经采取了吗?)
SamB

4
@SamB:虽然也可以使用not运算符,但don't care也没那么糟
Tobias Kienzler

28
请注意,这,不是可选的。只是打字[~ ~ var]工作,就会抛出一个错误。
eykanal 2011年

我会说这是“正确”的答案。另一个仅仅是解决不存在的问题的技巧。虽然没有双关语的意图……
patrik

6
该问题在R2009b之前的2009年提出,当时〜无效。
汤姆·安德森

37

如果您希望使用一种样式,其中会将变量保留在位桶中,那么合理的替代方法是

[ans,ans,variableThatIWillUse] = myfun(inputs);

ans当然是matlab的默认垃圾变量,在会话过程中经常会被覆盖。

尽管我确实喜欢MATLAB现在允许的新技巧,但使用〜来指定忽略的返回变量,但这是向后兼容的问题,因为较早版本的用户将无法使用您的代码。我通常避免使用这样的新事物,直到至少发布了几个MATLAB版本以确保很少有用户陷入困境。例如,即使现在我仍然发现人们仍在使用足够老的MATLAB版本,他们不能使用匿名函数。


7
是的,它很聪明,但是如果您将任何内容分配给ans变量,则本机Matlab编辑器将发出警告。我认为发出警告不是很优雅……
Jordi

11
您可以关闭警告。用此注释字符串%#ok结尾行,然后Mlint将忽略它。没有警告。

13

这是您可以使用的另一个选项。首先创建一个单元格数组以捕获所有输出(您可以使用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{3};  % Get the third output

9

我写了一个kth out函数:


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;
% global:
% nb: 
% See also:
% todo:
% changelog: 
%
%% %UNFOLD

[outargs{1:k}]  = feval(ffnc,varargin{:});
kth                         = outargs{k};

end %function

然后你可以打电话

val_i_want  = kthout(3,@myfunc,func_input_1,func_input_2); %etc

您也可以像这样包装功能

func_i_want = @(varargin)(kthout(3,@myfunc,varargin{:}));  %assuming you want the 3rd output.

之后您使用

val_i_want = func_i_want(func_input_1,func_input_2);

请注意,使用这样的匿名函数会产生开销,而这在我被数千次调用的代码中是不可行的。


4

在Matlab 2010a中,我发现了一种完成要求的巧妙方法。只需将字符“〜”(当然不带引号)用作您的虚拟变量(返回多个参数时,所需数量就可以了)。如果功能旨在处理丢失的数据,这也适用于功能的输入参数。我不知道它是否存在于以前的版本中,但是我最近才发现它。


11
您没有看到上一个答案吗?
yuk 2010年

1

您可以创建一个仅返回选定输出的函数(或匿名函数),例如

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);
NotGaeL 2012年

1
select(func,2)来电func(2)。我看不到它在哪里选择输出参数。
克里斯·伦戈

0

是否有任何不使用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中的函数根据输出参数的数量来更改行为。
克里斯·伦戈

我很难理解这个答案。我不知道这对这里答案的质量有何贡献,更不用说这不能直接回答原始问题了。
rayryeng

6年后,我不再使用Matlab。据我所记得,函数“ size()”是无关紧要的–我只是将其用作返回多个参数的函数。关键是我可以简单地调用func()然后再调用ans(n)来获取返回的变量编号n的值。这似乎在某些情况下效果很好,并且向后兼容。当然,它只能与某些功能或变量类型一起使用。六年后,我将竭尽所能。
user1596274'1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.