Wie kann man einige Rückgabewerte einer MATLAB-Funktion elegant ignorieren?

120

Ist es möglich, den 'n-ten' Rückgabewert von einer Funktion abzurufen, ohne vorher Dummy-Variablen für alle n-1Rückgabewerte erstellen zu müssen ?

Angenommen, ich habe die folgende Funktion in MATLAB:

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

Angenommen, ich interessiere mich nur für den dritten Rückgabewert. Dies kann durch Erstellen einer Dummy-Variablen erreicht werden:

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

Aber ich finde das irgendwie hässlich . Ich würde denken, dass Sie in der Lage sein könnten, so etwas wie eines der folgenden Dinge zu tun, aber Sie können nicht:

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

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

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


Bisher besteht die beste Lösung darin, die variableThatIWillUseVariable einfach als Dummy-Variable zu verwenden. Dies erspart mir die Erstellung einer echten Dummy-Variablen, die den Arbeitsbereich verschmutzt (oder die ich löschen müsste). Kurz gesagt: Die Lösung besteht darin, den variableThatIWillUseWert 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, dass dies ein sehr hässlicher Code ist, aber wenn es keinen besseren Weg gibt, werde ich die Antwort wahrscheinlich akzeptieren.

Jordi
quelle
Abgesehen von der Verwendung eines Zellenarrays, wie ich es in meiner Antwort beschrieben habe, ist das Wiederholen des Variablennamens wahrscheinlich Ihre einzige andere Lösung. Hoffentlich sind Ihre Variablennamen nicht so lang wie "variableThatIWillUse". =)
Gnovice
Eigentlich sind sie es. "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
26
Seit R2009b wird das Ignorieren von Funktionsrückgaben mit dem '~' -Char eleganter gelöst. zB: [~, b] = sort (rand (10,1))
ymihere
1
FÜR NEUE LESER: ^ sollte die richtige Antwort sein. Siehe die Antwort von ManWithSleeve unten
A.Wan
1
Wenn Sie in Ihrem Beispiel nur das dritte Ausgabeargument möchten, müssen Sie Folgendes verwenden: [variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func; Es ist nicht erforderlich, eine Dummy-Variable zu löschen. Verwenden Sie für neuere MATLAB-Versionen> = R2009b [~, ~, variableThatIWillUse] = func;
Thierry Dalon

Antworten:

38

Dies ist ein bisschen wie ein Hack, aber es funktioniert:

Zunächst eine kurze Beispielfunktion:

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

Der Schlüssel hier ist nun, dass, wenn Sie eine Variable auf der linken Seite einer Zuweisung mit mehreren Ausdrücken zweimal verwenden , eine frühere Zuweisung durch die spätere Zuweisung beeinträchtigt wird:

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

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

(Bearbeiten: Nur um zu überprüfen, habe ich auch überprüft, ob diese Technik funktioniert, [mu,mu,mu]=polyfit(x,y,n)wenn alles, was Sie interessiert, polyfitdas dritte Argument ist.)


edit: es gibt einen besseren Ansatz; Siehe stattdessen die Antwort von ManWithSleeve .

Jason S.
quelle
7
Hatte nicht daran gedacht, es so zu lösen. Ich bin jedoch der Meinung, dass diese Lösung die Klarheit der Absicht für Klugheit opfert.
Jukka Dahlbom
5
Ich persönlich benutze einfach [junk, junk, c] = function_call () und gehe davon aus, dass "junk" niemals eine wichtige Variable ist und wenn es viel Speicher enthält, werde ich es bei Bedarf löschen.
Jason S
5
an den Downvoter: Warum der -1? Diese Antwort wurde geschrieben, bevor R2009b überhaupt veröffentlicht wurde, sodass die Antwort von @ ManWithSleeve zu diesem Zeitpunkt nicht funktioniert hätte. Das ist natürlich der richtige Ansatz.
Jason S
2
Vielleicht wäre ein Kommentar in der ersten Zeile Ihrer Antwort hilfreich? Ich bin gerade über Google hierher gekommen, es scheint also eine Aktualisierung wert zu sein.
FvD
Die Zuordnung von links nach rechts wird von The MathWorks nicht offiziell garantiert, daher sollten Sie sich wahrscheinlich nicht auf die Verwendung von c nach [c, c, c] = myFunc () verlassen. (Siehe Kommentar # 26 hier: blogs.mathworks.com/loren/2009/09/11/… )
Matt Krause
226

Mit MATLAB Version 7.9 (R2009b) können Sie ein ~ verwenden, z.

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

Beachten Sie, dass das ,nicht optional ist. Nur das Tippen [~ ~ var]funktioniert nicht und wirft einen Fehler auf.

Weitere Informationen finden Sie in den Versionshinweisen.

ManWithSleeve
quelle
3
Ein bisschen nervig, dass es nicht "_" ist. (Ich nehme an, das wurde schon genommen?)
SamB
4
@ SamB: obwohl die Verwendung des notOperators wie in auch don't carenicht so schlecht ist
Tobias Kienzler
28
Beachten Sie, dass das ,nicht optional ist. Einfach mit der Eingabe [~ ~ var]wird nicht arbeiten, und wird einen Fehler werfen.
Eykanal
Ich würde sagen, dass dies die "richtige" Antwort ist. Die anderen sind nur Hacks, um ein Problem zu beheben, das nicht existiert. Kein Wortspiel beabsichtigt ...
Patrik
6
Die Frage wurde 2009 vor R2009b gestellt. Zu diesem Zeitpunkt funktionierte das ~ nicht.
Tom Anderson
37

Wenn Sie einen Stil verwenden möchten, bei dem eine Variable in den Bit-Bucket fällt, ist dies eine sinnvolle Alternative

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

ans ist natürlich die Standard-Junk-Variable für matlab, die im Verlauf einer Sitzung häufig überschrieben wird.

Ich mag zwar den neuen Trick, den MATLAB jetzt zulässt, indem ein ~ verwendet wird, um eine ignorierte Rückgabevariable zu kennzeichnen, dies ist jedoch ein Problem für die Abwärtskompatibilität, da Benutzer älterer Versionen Ihren Code nicht verwenden können. Ich vermeide es im Allgemeinen, solche neuen Dinge zu verwenden, bis mindestens einige MATLAB-Versionen veröffentlicht wurden, um sicherzustellen, dass nur noch sehr wenige Benutzer im Stich gelassen werden. Zum Beispiel finde ich, dass die Leute auch jetzt noch eine MATLAB-Version verwenden, die alt genug ist, um keine anonymen Funktionen verwenden zu können.


quelle
7
Ja, es ist klug, aber der native Matlab-Editor gibt eine Warnung aus, wenn Sie der Variablen ans etwas zuweisen. Ich denke nicht, dass Warnungen sehr elegant sind ...
Jordi
11
Sie können die Warnung ausschalten. Beenden Sie die Zeile mit dieser Kommentarzeichenfolge% # ok Mlint ignoriert dies dann. Keine Warnungen.
13

Hier ist eine weitere Option, die Sie verwenden können. Erstellen Sie zunächst ein Zellenarray, um alle Ausgaben zu erfassen (Sie können die NARGOUT- Funktion verwenden, um zu bestimmen, wie viele Ausgaben eine bestimmte Funktion zurückgibt):

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

Rufen Sie dann die Funktion wie folgt auf:

[a{:}] = func();

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

a = a{3};  % Get the third output
gnovice
quelle
9

Ich habe eine k-te Funktion geschrieben:


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 anrufen

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

Sie können die Funktion auch wie folgt abschließen

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

Danach verwenden Sie

val_i_want = func_i_want(func_input_1,func_input_2);

Beachten Sie, dass mit der Verwendung anonymer Funktionen wie dieser Overhead verbunden ist, und dies würde ich nicht in Code tun, der tausende Male aufgerufen wird.

shabbychef
quelle
4

In Matlab 2010a habe ich eine gute Möglichkeit gefunden, das zu tun, wonach Sie fragen. Es ist einfach, das Zeichen "~" (natürlich ohne Anführungszeichen) als Dummy-Variable zu verwenden (so viele, wie Sie möchten, wenn Sie mehrere Parameter zurückgeben). Dies funktioniert auch für Eingabeparameter für Funktionen, wenn die Funktionen für die Verarbeitung fehlender Daten ausgelegt sind. Ich weiß nicht, ob dies in früheren Versionen vorhanden war, aber ich bin erst kürzlich darauf gestoßen.

Sam
quelle
11
Hast du die vorherige Antwort nicht gesehen?
Yuk
1

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

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

Dann können Sie Ihre Funktion folgendermaßen 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);
Dave
quelle
funktioniert nicht für mich. Versuchtdecimatedfftx = select(fft(x,12),1:4:12);
NotGaeL
1
select(func,2)Anrufe func(2). Ich sehe nicht, wo dies Ausgabeargumente auswählt.
Cris Luengo
0

Gibt es einen Grund, ans (n) nicht wie folgt zu verwenden:

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

size(a);

b=ans(2);

Gibt b = 10 und wäre dieser Weg nicht mit allen Matlab-Versionen kompatibel?

Außerdem funktioniert dies, um das zweite Ausgabeargument zu erhalten, wenn Sie nicht wissen, wie viele Argumente es geben wird! Wenn Sie dies tun:

[~, b] = size(a);

Dann ist b = 8000! (Sie müssen mit ~ enden, um mehr Argumente zu fangen!)

user1596274
quelle
Diese Antwort geht davon aus, dass die zurückgegebene Variable ein Vektor ist, was wahrscheinlich nicht das war, was das OP bedeutete.
Neil Traft
Das macht keinen Sinn. size(a)und [b,c]=size(a)verschiedene Dinge zurückgeben. Funktionen in MATLAB ändern das Verhalten basierend auf der Anzahl der Ausgabeargumente.
Cris Luengo
Es fällt mir schwer, diese Antwort zu verstehen. Ich weiß nicht, wie dies zur Qualität der Antworten hier beiträgt, geschweige denn, dass dies die ursprüngliche Frage nicht direkt beantwortet.
Rayryeng
Es ist 6 Jahre später und ich benutze Matlab nicht mehr. Soweit ich mich erinnere, war die Funktion "size ()" irrelevant - ich habe sie nur als Funktion verwendet, die mehrere Argumente zurückgibt. Der Punkt ist, dass ich einfach func () und dann ans (n) aufrufen kann, um den Wert der zurückgegebenen Variablennummer n zu erhalten. Dies schien in bestimmten Situationen gut zu funktionieren und abwärtskompatibel zu sein. Es kann natürlich nur mit bestimmten Funktionen oder Variablentypen funktionieren. Das ist so viel, wie ich 6 Jahre später helfen kann.
user1596274