2009-04-14 8 views
110

Ist es möglich, den Rückgabewert 'nth' von einer Funktion zu erhalten, ohne dass zuvor Dummy-Variablen für alle n-1 Rückgabewerte erstellt werden müssen?Wie ignoriert man elegant einige Rückgabewerte einer MATLAB-Funktion?

Lassen Sie uns sagen, ich die folgende Funktion in MATLAB haben:

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

Nehmen wir nun an, ich bin daran interessiert sind nur in den dritten Rückgabewert. Dies kann durch Erstellen einer Dummy-Variablen erreicht werden:

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

Aber ich denke, das ist eine Art von hässlich. Ich würde denken, dass Sie in der Lage sein könnte, so etwas wie eine der folgenden Dinge zu tun, aber Sie können nicht:

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

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

Gibt es alle elegant Möglichkeiten, dies zu tun, die funktionieren?


Bisher ist die beste Lösung, um einfach die variableThatIWillUse als Dummy-Variable zu verwenden. Dies erspart mir, eine echte Dummy-Variable zu erstellen, die den Arbeitsplatz verunreinigt (oder die ich löschen müsste). Kurz gesagt: Die Lösung besteht darin, die variableThatIWillUse für jeden Rückgabewert bis zum interessanten zu verwenden. Rückgabewerte nach können einfach ignoriert werden:

[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func; 

Ich denke immer noch, diese sehr hässlich Code ist, aber wenn es keinen besseren Weg gibt, dann denke ich, werde ich die Antwort akzeptieren.

+0

Abgesehen von der Verwendung eines Zellenarrays, wie ich es in meiner Antwort beschrieben habe, ist die Wiederholung des Variablennamens wahrscheinlich Ihre einzige andere Lösung. Hoffentlich sind Ihre Variablennamen nicht so lang wie "variableThatIWillUse". =) – gnovice

+0

Eigentlich sind sie. "Dummy" war nur ein Beispiel. Normalerweise würde ich 'variableThatIWillNotUse' verwenden. Andere Variablen heißen 'variableThatIMightUse', 'variableThatIWillUse2' und 'variableThatCanBarelyFitOnA80CharacterLine'. Ich untersuche die Korrelation zwischen langen Namen und Mordraten. ;) – Jordi

+23

Tatsächlich wird die R2009b-Ignorierfunktion mit dem '~' -Char eleganter gelöst. zB: [~, b] = sort (rand (10,1)) – ymihere

Antwort

37

Das ist so etwas wie ein Hack, aber es funktioniert:

Zuerst ein kurzes Beispiel Funktion:

Func3 = @() deal(1,2,3); 
[a,b,c]=Func3(); 
% yields a=1, b=2, c=3 

Jetzt hier der Schlüssel ist, dass, wenn Sie verwenden, um eine Variable zweimal in der linken Seite durch die spätere Zuordnung einer Zuordnung mehrere Ausdrucks, eine frühere Zuordnung verprügelt wird:

[b,b,c]=Func3(); 
% yields b=2, c=3 

[c,c,c]=Func3(); 
% yields c=3 

(edit: nur um zu überprüfen, Ich überprüfte auch, dass diese Technik mit [mu,mu,mu]=polyfit(x,y,n) funktioniert, wenn alles, was Sie über Pflege von polyfit das dritte Argument ist)


edit: es gibt einen besseren Ansatz; siehe ManWithSleeve's answer stattdessen.

+7

Hätte nicht gedacht, es so zu lösen. Ich denke jedoch, dass diese Lösung die Klarheit der Absicht für Cleverness opfert. –

+5

Ich persönlich benutze einfach [junk, junk, c] = function_call() und nehme an, dass beide "Junk" nie eine wichtige Variable ist und wenn es viel Speicher enthält, werde ich es bei Bedarf löschen. –

+0

Das gleiche hier, damals, als ich mit MATLAB gearbeitet habe. –

12

Hier ist eine weitere Option, die Sie verwenden können.Erste, der eine Zellenfeld machen alle Ausgänge zu erfassen (können Sie die NARGOUT Funktion bestimmen, wie viele Ausgänge eine gegebene Funktion Returns):

a = cell(1,3); % For capturing 3 outputs 
% OR... 
a = cell(1,nargout(@func)); % For capturing all outputs from "func" 

Dann rufen Sie die Funktion wie folgt:

[a{:}] = func(); 

Dann entfernen Sie einfach das Element aus ein, die Sie möchten, und überschreiben eine:

a = a{3}; % Get the third output 
36

Wenn Sie einen Stil verwenden, wo eine Variable wird gelassen in den Bit-Eimer fallen, dann eine sinnvolle Alternative ist

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

ans natürlich ist die Standard-Junk-Variable für Matlab, in der oft überschrieben bekommen Kurs einer Sitzung.

Obwohl ich den neuen Trick mag, den MATLAB jetzt zulässt, ist die Abwärtskompatibilität mit einem ~ problematisch, da Benutzer älterer Versionen Ihren Code nicht verwenden können. Ich vermeide im Allgemeinen solche neuen Dinge, bis mindestens ein paar MATLAB-Releases herausgegeben wurden, um sicherzustellen, dass nur sehr wenige Benutzer im Stich gelassen werden. Zum Beispiel finde ich, dass Leute immer noch eine alte MATLAB-Version verwenden, die keine anonymen Funktionen verwenden kann.

+6

Ja, es ist clever, aber der native Matlab-Editor gibt eine Warnung aus, wenn Sie der ans-Variablen etwas zuweisen. Ich glaube nicht, dass Warnungen sehr elegant sind ... – Jordi

+10

Sie können die Warnung ausschalten. Beenden Sie die Zeile mit dieser Kommentarzeichenfolge% # ok Mlint ignoriert dies. Keine Warnungen. –

9

Ich schrieb einen k-ten-out-Funktion:


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

Sie können dann rufen

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

Sie auch die Funktion einpacken könnte wie

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

nach dem Sie

verwenden
val_i_want = func_i_want(func_input_1,func_input_2); 

Beachten Sie, dass mit dem Verwenden von anonymen Funktionen wie diesem ein Overhead verbunden ist, und das ist nichts, was ich in Code tun würde, der tausende Male aufgerufen würde.

214

Mit MATLAB Version 7.9 (R2009b) Sie ~, zum Beispiel

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

Beachten Sie, dass die , nicht optional verwenden können. Die Eingabe von [~ ~ var] funktioniert nicht und es wird ein Fehler ausgegeben.

Siehe die release notes für Details.

+3

Irgendwie ärgerlich, dass es nicht "_" ist. (Ich nehme an, dass wurde schon vergeben?) – SamB

+3

@SamB: obwohl die Verwendung des "nicht" -Operators wie in "egal" ist nicht so schlecht –

+26

Beachten Sie, dass die ',' ist nicht optional. Wenn Sie nur '[~ ~ var]' eingeben, funktioniert * * * nicht und es wird ein Fehler ausgegeben. – eykanal

4

In Matlab 2010a fand ich eine nette Art zu tun, was Sie verlangen. Es ist einfach, das Zeichen "~" (ohne die Anführungszeichen natürlich) als Dummy-Variable zu verwenden (so viele, wie Sie möchten, wenn Sie mehrere Parameter zurückgeben). Dies funktioniert auch bei Eingabeparametern für Funktionen, wenn die Funktionen für die Behandlung fehlender Daten ausgelegt sind. Ich weiß nicht, ob das in früheren Versionen existierte, aber ich bin erst kürzlich darauf gestoßen.

+10

Haben Sie die vorherige Antwort nicht gesehen? – yuk

3

Sie können eine Funktion (oder anonyme Funktion) erstellen, die nur ausgewählte Ausgaben zurückgibt, z.

select = @(a,b) a(b); 

Dann können Sie Ihre Funktion wie folgt aufrufen:

select(func,2); 
select(func,1:3); 

Oder Sie können die Ausgabe einer Variablen zuweisen:

output(1,2:4) = select(func,1:3); 
+0

funktioniert nicht für mich. Versucht 'decimatedfftx = select (fft (x, 12), 1: 4: 12);' – NotGaeL

-1

ich gefunden habe, wenn Sie nur eine einzige wollen Ausgabe können Sie die Funktion multiplizieren mit Einheitsmatrix, die der gewünschten Ausgabe entspricht. dh out_arg_the_third = function (input_args) * [0; 0; 1; 0];

oder komplexer werden, können Sie die Dimensionen Ihrer Matrix erweitern, um mehr Ausgaben zu sammeln: out_arg_second_and_third = function (input_args) * [0,0; 1,0; 0,1; 0,0]; aber wir verlieren hier etwas Eleganz.

Es muss bessere Möglichkeiten, mit den neueren Versionen, aber aus Gründen, die ich nicht verstehe ich 2007b

2

verwenden müssen Gibt es einen Grund, nicht am (n), wie diese zu verwenden:

a=rand([5 10 20 40]); 

size(a); 

b=ans(2); 

Gibt b = 10, und wäre auf diese Weise nicht mit allen Matlab-Versionen kompatibel?

Darüber hinaus funktioniert dies, um das zweite Ausgabeargument zu erhalten, wenn Sie nicht wissen, wie viele Argumente es gibt! Wenn Sie dies tun:

[~, b] = size(a); 

Dann b = 8000! (Sie müssen mit ~ enden, um weitere Argumente abzufangen!)

+0

Diese Antwort geht davon aus, dass die zurückgegebene Variable ein Vektor ist, was wahrscheinlich nicht das war, was das OP bedeutete. –

Verwandte Themen