Come ignorare elegantemente alcuni valori di ritorno di una funzione MATLAB?

È ansible ottenere l’ennesimo valore di ritorno da una funzione senza dover creare variabili dummy per tutti i valori di ritorno n-1 prima di esso?

Diciamo, ho la seguente funzione in MATLAB:

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

Supponiamo che io sia interessato solo al terzo valore di ritorno. Questo può essere ottenuto creando una variabile dummy:

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

Ma penso che questo sia un po ‘ brutto . Penserei che potresti essere in grado di fare qualcosa come una delle seguenti cose, ma non puoi:

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

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

Ci sono modi eleganti per fare questo che funzionano?


Finora, la soluzione migliore è semplicemente usare la variableThatIWillUse come variabile fittizia. Ciò mi evita di dover creare una variabile fittizia reale che inquini lo spazio di lavoro (o che avrei bisogno di cancellare). In breve: la soluzione è utilizzare la variableThatIWillUse per ogni valore restituito fino a quello interessante. I valori di ritorno dopo possono semplicemente essere ignorati:

 [variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func; 

Continuo a pensare che questo sia un codice molto brutto, ma se non c’è modo migliore, suppongo che accetterò la risposta.

Questo è un po ‘un trucco, ma funziona:

Innanzitutto una rapida funzione di esempio:

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

Ora, la chiave qui è che se si utilizza una variabile due volte nella parte sinistra di un incarico a più espressioni, un incarico precedente viene scombussolato dall’assegnazione successiva:

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

(edit: solo per verificare, ho anche verificato che questa tecnica funziona con [mu,mu,mu]=polyfit(x,y,n) se tutto quello che ti interessa da polyfit è il terzo argomento)


modifica: c’è un approccio migliore; vedi invece la risposta di ManWithSleeve .

Con MATLAB versione 7.9 (R2009b) puoi usare un ~, ad es.

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

Si noti che il , non è opzionale. Digitare [~ ~ var] non funzionerà e genererà un errore.

Vedi le note di rilascio per i dettagli.

Se si desidera utilizzare uno stile in cui una variabile verrà lasciata cadere nel bucket di bit, allora è un’alternativa ragionevole

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

ans è ovviamente la variabile junk predefinita per MATLAB, che viene sovrascritta spesso nel corso di una sessione.

Anche se mi piace il nuovo trucco che MATLAB ora consente, utilizzando un ~ per designare una variabile di ritorno ignorata, questo è un problema di compatibilità con le versioni precedenti, in quanto gli utenti di versioni precedenti non saranno in grado di utilizzare il codice. In genere evito di usare cose nuove come questa, almeno fino a quando non sono state rilasciate alcune versioni di MATLAB per garantire che ci siano pochissimi utenti rimasti in asso. Ad esempio, anche ora trovo che le persone stiano ancora utilizzando una versione MATLAB abbastanza vecchia da non poter usare funzioni anonime.

Ecco un’altra opzione che puoi usare. Per prima cosa crea un array di celle per catturare tutte le uscite (puoi usare la funzione NARGOUT per determinare quanti output restituisce una determinata funzione):

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

Quindi chiama la funzione come segue:

 [a{:}] = func(); 

Quindi rimuovi semplicemente l’elemento da quello desiderato e sovrascrivi un :

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

Ho scritto una funzione 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 

puoi quindi chiamare

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

potresti anche concludere la funzione come

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

dopo di che usi

 val_i_want = func_i_want(func_input_1,func_input_2); 

nota che c’è un sovraccarico associato all’utilizzo di funzioni anonime come questa, e questo non è qualcosa che farei nel codice che verrebbe chiamato migliaia di volte.

In Matlab 2010a, ho trovato un modo pulito di fare ciò che stai chiedendo. È semplicemente usare il characher “~” (senza le virgolette ovviamente) come variabile dummy (quante ne vuoi quando si restituiscono più parametri). Questo funziona anche per i parametri di input per le funzioni se le funzioni sono progettate per gestire i dati mancanti. Non so se questo esisteva nelle versioni precedenti, ma l’ho appena visto di recente.

È ansible eseguire una funzione (o funzione anonima) che restituisce solo le uscite selezionate, ad es

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

Quindi puoi chiamare la tua funzione in questo modo:

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

Oppure puoi assegnare l’output a una variabile:

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

C’è qualche ragione per non usare ans (n), come questo:

 a=rand([5 10 20 40]); size(a); b=ans(2); 

Fornisce b = 10, e in questo modo non sarebbe compatibile con tutte le versioni di Matlab?

Inoltre, questo funziona per ottenere il secondo argomento di output quando non sai quanti argomenti ci saranno! Considerando che, se lo fai:

 [~, b] = size(a); 

Quindi b = 8000! (Devi finire con ~, per prendere più argomenti!)

Ho scoperto che se vuoi un singolo output puoi crossare moltiplicare la funzione con una matrice unitaria corrispondente all’output desiderato. ie out_arg_the_third = function (input_args) * [0; 0; 1; 0];

o diventando più complesso, puoi espandere le dimensioni della tua matrice per raccogliere più output: out_arg_second_and_third = function (input_args) * [0,0; 1,0; 0,1; 0,0]; ma stiamo iniziando a perdere un po ‘di eleganza qui.

Ci devono essere modi migliori con le versioni più recenti ma per ragioni che non capisco devo usare 2007b