2009-04-14 16 views
110

Czy jest możliwe uzyskanie "n-tej" wartości zwracanej z funkcji bez konieczności tworzenia fałszywych zmiennych dla wszystkich wartości zwracanych przed wartością n-1?Jak elegancko zignorować niektóre zwracane wartości funkcji MATLAB?

Powiedzmy, mam następującą funkcję w programie MATLAB:

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

Załóżmy teraz, jestem zainteresowany tylko wartości zwracanej trzeci. Można to osiągnąć poprzez stworzenie jednej zmiennej manekina:

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

Ale myślę, że jest to rodzaj brzydkiego. tam

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

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

są: Myślę, że może być w stanie coś zrobić jak jeden z następujących rzeczy, ale nie można każdy elegancki sposoby to zrobić, które działają?


Dotychczas najlepszym rozwiązaniem jest po prostu użyć variableThatIWillUse jako zmienną manekina. To oszczędza mi konieczności stworzenia prawdziwej sztucznej zmiennej, która zanieczyszcza przestrzeń roboczą (lub którą musiałbym usunąć). W skrócie: rozwiązaniem jest użycie wartości variableThatIWillUse dla każdej wartości zwracanej aż do interesującej. Powrót wartości po prostu może być ignorowane:

[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func; 

Nadal uważam, że to jest bardzo brzydki kodu, ale jeśli nie ma lepszego sposobu, to chyba będę akceptować odpowiedź.

+0

Oprócz użycia tablicy komórek, jak opisałem w mojej odpowiedzi, powtarzanie nazwy zmiennej jest prawdopodobnie twoim jedynym rozwiązaniem. Mam nadzieję, że nazwy zmiennych nie są tak długie, jak "variableThatIWillUse". =) – gnovice

+0

W rzeczywistości są. "manekin" był tylko przykładem. Normalnie użyłbym "variableThatIWillNotUse". Inne zmienne mają nazwy "variableThatIMightUse", "variableThatIWillUse2" i "variableThatCanBarelyFitOnA80CharacterLine". Badam korelację między długimi nazwami a ocenami zabójstw. ;) – Jordi

+23

Faktycznie od kiedy funkcja zwracająca ignoruje funkcję R2009b jest rozwiązywana bardziej elegancko za pomocą '~' -Char. np .: [~, b] = sort (rand (10,1)) – ymihere

Odpowiedz

37

Jest to nieco hack, ale działa:

pierwsze szybkie przykład funkcja:

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

Teraz kluczem tutaj jest to, że jeśli używasz zmiennej dwukrotnie w lewym skrzydle z przypisania wielu wyrażenie, wcześniejsze przypisanie jest niszczona przez późniejszego przydziału:

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

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

(edit: tylko do sprawdzenia, I sprawdziła również, że technika ta działa z [mu,mu,mu]=polyfit(x,y,n) jeśli wszystko zależy od polyfit jest 3rd argumentem)


edit: tam jest lepszym rozwiązaniem; zamiast tego zobacz ManWithSleeve's answer.

+7

Nie myślałem o rozwiązaniu tego w ten sposób. Jednak czuję, że to rozwiązanie poświęca jasność zamiaru sprytu. –

+5

Osobiście używam [śmieć, śmieci, c] = function_call() i zakładam, że zarówno "śmieci" nigdy nie są ważnymi zmiennymi i jeśli zawierają dużo pamięci, które wyczyszczę, jeśli to konieczne. –

+0

To samo, kiedy pracowałem z MATLAB. –

12

Oto kolejna opcja, której można użyć.Najpierw zrobić tablicę komórek do przechwytywania wszystkich wyjść (można użyć funkcji NARGOUT aby określić ile wyjść danego zwrotu funkcji):

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

Następnie wywołać funkcję w następujący sposób:

[a{:}] = func(); 

Następnie po prostu usunąć element z że chcesz, i nadpisać się:

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

Jeśli chcesz użyć stylu gdzie zmienna będzie pozostawiony wpaść w wiadrze bitowym, to rozsądna alternatywa jest

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

ans jest oczywiście zmienna domyślna śmieci za Matlab, uzyskiwanie nadpisane często w przebieg sesji.

Chociaż podoba mi się nowa sztuczka, na którą pozwala teraz MATLAB, użycie ~ do oznaczenia ignorowanej zmiennej powrotnej stanowi problem z kompatybilnością wsteczną, ponieważ użytkownicy starszych wersji nie będą mogli używać Twojego kodu. Zwykle nie używam nowych rzeczy, dopóki nie wydano przynajmniej kilku wydań MATLAB, aby zapewnić, że będzie bardzo mało użytkowników. Na przykład, nawet teraz widzę, że ludzie wciąż używają wystarczająco starej wersji MATLAB, że nie mogą używać anonimowych funkcji.

+6

Tak, jest to sprytne, ale natywny edytor Matlab wyświetli ostrzeżenie, jeśli cokolwiek zostanie przypisane do zmiennej ans. Nie sądzę, aby ostrzeżenia były bardzo eleganckie ... – Jordi

+10

Możesz wyłączyć ostrzeżenie. Koniec linii z tym łańcuchem komentarza% # ok Mlint zignoruje to. Brak ostrzeżeń. –

9

Napisałem KTH się funkcję:


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

Można połączyć

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

można również zawinąć funkcję jak

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

po czym użyć

val_i_want = func_i_want(func_input_1,func_input_2); 

Zauważ, że istnieje nadmiar związany z używaniem takich anonimowych funkcji, a to nie jest coś, co zrobiłbym w kodzie, który byłby nazywany tysiące razy.

214

z Matlab w wersji 7.9 (R2009b) można wykorzystać do ~, na przykład

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

Należy pamiętać, że , nie jest obowiązkowe. Po prostu wpisanie [~ ~ var] nie zadziała i spowoduje błąd.

Aby uzyskać szczegółowe informacje, patrz release notes.

+3

Trochę irytujące, że nie jest "_". (Przypuszczam, że zostało to już podjęte?) – SamB

+3

@SamB: chociaż użycie operatora 'not', jak w' nie obchodzi ', nie jest takie złe albo –

+26

Zauważ, że ',' nie jest opcjonalne. Po prostu wpisanie '[~ ~ var]' będzie * nie * działało i spowoduje błąd. – eykanal

4

W programie Matlab 2010a znalazłem sposób na zrobienie tego, o co prosisz. Chodzi po prostu o to, aby użyć "nauczyciela" (bez cudzysłowów) jako swojej sztucznej zmiennej (tyle, ile chcesz, gdy zwracasz wiele parametrów). Działa to również dla parametrów wejściowych do funkcji, jeśli funkcje są zaprojektowane do obsługi brakujących danych. Nie wiem, czy istniało to w poprzednich wersjach, ale niedawno się z tym spotkałem.

+10

Nie widzisz poprzedniej odpowiedzi? – yuk

3

Można utworzyć funkcję (lub funkcję anonimową), która zwraca tylko wybrane wyjścia, np.

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

Następnie można wywołać czynność tak:

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

Albo można przypisać wyjście do zmiennej:

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

nie działa dla mnie. Próbowano 'decimatedfftx = select (fft (x, 12), 1: 4: 12);' – NotGaeL

-1

ja znaleźć, jeśli tylko chcą pojedyncza wyjście możesz krzyżować mnożenie funkcji z macierzą jednostki odpowiadającą żądanemu wynikowi. tj. out_arg_the_third = funkcja (input_args) * [0; 0; 1; 0];

lub uzyskanie bardziej złożonych, można rozszerzyć wymiary macierzy w celu zebrania większej wydajności: out_arg_second_and_third = function (input_args) * [0,0; 1,0; 0,1; 0,0]; , ale zaczynamy tracić nieco elegancji.

Musi być lepsze sposoby z nowszych wersjach, ale z powodów, których nie rozumiem muszę korzystać 2007b

2

Czy jest jakiś powód, aby nie używać ans (n), na przykład:

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

size(a); 

b=ans(2); 

Daje b = 10, i czy w ten sposób nie będzie kompatybilny ze wszystkimi wersjami Matlab?

Co więcej, działa to, aby uzyskać drugi argument wyjściowy, gdy nie wiesz, ile argumentów będzie! Natomiast jeśli to zrobisz:

[~, b] = size(a); 

Następnie b = 8000! (Koniec z ~, aby przechwycić więcej argumentów!)

+0

Ta odpowiedź zakłada, że ​​zwracana zmienna jest wektorem, co prawdopodobnie nie było tym, co oznaczało PO. –

Powiązane problemy