ChatGPT解决这个技术问题 Extra ChatGPT

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

是否可以从函数中获取“第 n 个”返回值,而不必为之前的所有 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”那么长。 =)
其实他们是。 'dummy' 只是一个例子。通常我会使用'variableThatIWillNotUse'。其他变量名为“variableThatIMightUse”、“variableThatIWillUse2”和“variableThatCanBarelyFitOnA80CharacterLine”。我正在研究长名字和凶杀等级之间的相关性。 ;)
实际上,由于 R2009b 忽略函数返回,因此使用 '~'-Char 可以更优雅地解决。例如:[~,b] = sort(rand(10,1))
对于新读者: ^ 应该是正确的答案。请参阅下面的ManWithSleeve's answer
在您的示例中,如果您只想使用第三个输出参数:[ variableThatIWillUse,variableThatIWillUse,variableThatIWillUse] = func;无需清除虚拟变量。对于较新的 MATLAB 版本 >=R2009b,请使用 [~,~,variableThatIWillUse] = func;

p
pauldoo

使用 MATLAB 版本 7.9 (R2009b),您可以使用 ~,例如,

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

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

有关详细信息,请参阅 release notes


有点烦人,它不是“_”。 (我想那已经被拍了?)
@SamB:虽然在 don't care 中使用 not 运算符也不是那么糟糕
请注意,, 不是可选的。仅键入 [~ ~ var]起作用,并且会引发错误。
我会说这是“正确”的答案。另一个只是解决不存在的问题的技巧。虽然没有双关语...
该问题是在 R2009b 之前的 2009 年提出的,当时 ~ 不起作用。
P
Peter Mortensen

这有点像黑客,但它有效:

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

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

(只是为了检查,如果您只关心 polyfit 中的第三个参数,我还验证了此技术适用于 [mu,mu,mu]=polyfit(x,y,n)。)

有更好的方法;请参阅 ManWithSleeve's answer


没想到这样解决。然而,我觉得这个解决方案为了聪明而牺牲了意图的清晰性。
我个人只是使用 [junk, junk, c] = function_call() 并假设“垃圾”从来都不是一个重要的变量,如果它包含大量内存,我会在必要时将其清除。
对downvoter:为什么是-1?这个答案是在 R2009b 甚至发布之前写的,所以@ManWithSleeve 的答案在当时是行不通的。现在,当然,这是正确的方法。
也许您答案的第一行中的评论会有所帮助?我只是通过谷歌来到这里,所以它似乎值得更新。
The MathWorks 并未正式保证从左到右的赋值,因此您可能不应该依赖在 [c,c,c] = myFunc() 之后使用 c。 (请参阅此处的评论 #26:blogs.mathworks.com/loren/2009/09/11/…
P
Peter Mortensen

如果您希望使用将变量留在位桶中的样式,那么一个合理的选择是

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

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

虽然我确实喜欢 MATLAB 现在允许的新技巧,即使用 ~ 指定忽略的返回变量,但这是向后兼容性的问题,因为旧版本的用户将无法使用您的代码。

在至少发布几个 MATLAB 版本之前,我通常会避免使用类似的新东西,以确保只有很少的用户会陷入困境。例如,即使现在我发现人们仍在使用足够旧的 MATLAB 版本,以至于他们无法使用匿名函数。


是的,它很聪明,但是如果你给 ans 变量赋值,原生的 Matlab 编辑器会给出警告。我不认为有警告是非常优雅的......
您可以关闭警告。以这个注释字符串结束行 %#ok Mlint 将忽略它。没有警告。
g
glglgl

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

C
Cris Luengo

我写了一个第 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;

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

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);

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


P
Peter Mortensen

在 MATLAB 2010a 中,我找到了一种巧妙的方式来满足您的要求。

它只是使用字符“~”(当然不带引号)作为你的虚拟变量(返回多个参数时,你想要多少就多少)。如果函数旨在处理丢失的数据,这也适用于函数的输入参数。

我不知道这是否存在于以前的版本中,但我最近才遇到它。


没看到前面的回答吗?
涵盖在之前的两个答案中。
D
Dave

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

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)。我看不出它在哪里选择输出参数。
u
user1596274

我看不出有任何理由不使用 ans(n)。像这样:

size(rand([5 10 20 40]));

b = ans(2);

它给出 b = 10,这种方式将与所有 MATLAB 版本兼容。请注意,此处的 size() 仅用于表示具有多个返回变量的任何函数。

此外,当您不知道会有多少参数时,这可以获取第二个输出参数!然而,如果你这样做:

[~, b] = size(a);

那么b = 8000! (您需要以 ~ 结尾,以获取更多参数!)


这个答案假设返回的变量是一个向量,这可能不是 OP 的意思。
这是没有意义的。 size(a)[b,c]=size(a) 返回不同的东西。 MATLAB 中的函数会根据输出参数的数量改变行为。
我很难理解这个答案。我不知道这对这里答案的质量有何贡献,更不用说这不能直接回答原始问题。
6年后,我不再使用Matlab。据我记得,函数“size()”是无关紧要的——我只是将它用作一个返回多个参数的函数。关键是我可以简单地调用 func() 然后调用 ans(n) 来获取返回的变量号 n 的值。这似乎适用于某些情况并且向后兼容。当然,它可能只适用于某些函数,或者变量类型,无论如何。 6年后我能帮到的就这么多了。