Bir MATLAB işlevinin bazı dönüş değerleri nasıl zarif bir şekilde göz ardı edilir?


120

Ondan önceki tüm n-1dönüş değerleri için kukla değişkenler oluşturmak zorunda kalmadan bir fonksiyondan 'n'inci' dönüş değerini almak mümkün müdür ?

Diyelim ki MATLAB'da aşağıdaki işleve sahibim:

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

Şimdi varsayalım, ben sadece üçüncü dönüş değeri ile ilgileniyorum . Bu, bir kukla değişken oluşturarak gerçekleştirilebilir:

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

Ama bunun biraz çirkin olduğunu düşünüyorum . Aşağıdakilerden biri gibi bir şey yapabileceğinizi düşünürdüm, ancak yapamazsınız:

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

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

Bunu yapmanın işe yarayan zarif yolları var mı?


Şimdiye kadar, en iyi çözüm basit variableThatIWillUsebir değişken olarak kullanmaktır . Bu beni, çalışma alanını kirleten (veya temizlemem gereken) gerçek bir kukla değişken yaratma zorunluluğundan kurtarıyor. Kısaca: Çözüm, variableThatIWillUseilginç olana kadar her dönüş değeri için kullanmaktır . Sonrasında dönen değerler göz ardı edilebilir:

[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;

Hala bunun çok çirkin bir kod olduğunu düşünüyorum, ancak daha iyi bir yol yoksa sanırım cevabı kabul edeceğim.


Cevabımda anlattığım gibi bir hücre dizisi kullanmanın yanı sıra, değişken adını tekrarlamak muhtemelen diğer çözümünüzdür. Umarım değişken adlarınız "variableThatIWillUse" kadar uzun değildir. =)
gnovice

Aslında öyleler. "kukla" sadece bir örnekti. Normalde 'variableThatIWillNotUse' kullanırdım. Diğer değişkenler 'variableThatIMightUse', 'variableThatIWillUse2' ve 'variableThatCanBarelyFitOnA80CharacterLine' olarak adlandırılır. Uzun isimlerle cinayet derecelendirmeleri arasındaki ilişkiyi araştırıyorum. ;)
Jordi

26
Aslında, R2009b işlev dönüşlerini göz ardı ettiğinden beri, '~' -Char kullanılarak daha zarif bir şekilde çözülür. örneğin: [~, b] = sırala (rand (10,1))
ymihere

1
YENİ OKUYUCULAR İÇİN: ^ doğru cevap olmalıdır. Aşağıdaki ManWithSleeve'nin cevabına bakın
A.

1
Örneğinizde, yalnızca 3. çıktı argümanını istiyorsanız, kullanmalısınız: [variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func; Sahte bir değişkeni silmeye gerek yok. Daha yeni MATLAB sürümleri> = R2009b için [~, ~, variableThatIWillUse] = func;
Thierry Dalon

Yanıtlar:


38

Bu biraz hack gibi ama işe yarıyor:

İlk önce hızlı bir örnek işlevi:

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

Şimdi buradaki anahtar, bir değişken kullanıyorsanız çoklu ifadeli bir atamanın sol tarafında iki kez , daha önceki bir atama sonraki atama tarafından bozulur:

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

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

(düzenleme: sadece kontrol etmek için, bu tekniğin birlikte çalıştığını da doğruladım. [mu,mu,mu]=polyfit(x,y,n) eğer ilgilendiğiniz tek şey polyfit3. argüman ise )


düzenleme: daha iyi bir yaklaşım var; bunun yerine ManWithSleeve'nin cevabına bakın .


7
Bunu böyle çözmeyi düşünmemiştim. Bununla birlikte, bu çözümün zekâ niyetinin netliğini feda ettiğini düşünüyorum.
Jukka Dahlbom

5
Şahsen ben sadece [önemsiz, önemsiz, c] = function_call () kullanıyorum ve hem "çöp" ün asla önemli bir değişken olmadığını ve çok fazla bellek içeriyorsa, gerekirse onu temizleyeceğimi varsayıyorum.
Jason S

5
aşağı oy verene: Neden -1? Bu cevap R2009b yayınlanmadan önce yazılmıştır, bu nedenle @ ManWithSleeve'nin cevabı o zaman işe yaramazdı. Şimdi, tabii ki, doğru yaklaşım bu.
Jason S

2
Belki cevabınızın ilk satırına bir yorum yardımcı olabilir mi? Buraya az önce google üzerinden geldim, bu yüzden güncellenmeye değer görünüyor.
2013, 05

Soldan sağa atama, The MathWorks tarafından resmi olarak garanti edilmez, bu nedenle muhtemelen [c, c, c] = myFunc () 'dan sonra c kullanmaya güvenmemelisiniz. (Burada Yorum # 26'ya bakın: blogs.mathworks.com/loren/2009/09/11/… )
Matt Krause

226

MATLAB Sürüm 7.9 (R2009b) ile bir ~ kullanabilirsiniz, örn.

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

,İsteğe bağlı olmadığını unutmayın . Sadece yazmak [~ ~ var]işe yaramaz ve bir hata verir.

Ayrıntılar için sürüm notlarına bakın.


3
"_" Olmaması sinir bozucu. (Sanırım bu zaten alınmıştı?)
SamB

4
@SamB: notOperatörü olduğu gibi kullanmak o kadar don't careda kötü değil
Tobias Kienzler

28
Bunun ,isteğe bağlı olmadığını unutmayın . Sadece yazarak [~ ~ var]will not çalışmaları ve bir hata verir.
eykanal

Bunun "doğru" cevap olduğunu söyleyebilirim. Diğeri, var olmayan bir sorunu çözmek için yapılan hacklerdir. Hiç bir kelime anlamı yok ...
patrik

6
Soru 2009'da R2009b'den önce sorulmuştu ve o sırada ~ işe yaramadı.
Tom Anderson

37

Bir değişkenin bit kovasına düşmeye bırakılacağı bir stil kullanmak istiyorsanız, makul bir alternatif:

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

ans elbette matlab için varsayılan önemsiz değişkendir ve oturum sırasında sıklıkla üzerine yazılır.

MATLAB'ın artık izin verdiği yeni hileyi sevmeme rağmen, göz ardı edilen bir dönüş değişkenini belirtmek için a ~ kullanarak, bu geriye dönük uyumluluk için bir sorundur, çünkü eski sürümlerin kullanıcıları kodunuzu kullanamaz. Genelde, çok az sayıda kullanıcının kalmasını sağlamak için en az birkaç MATLAB sürümü yayınlanana kadar böyle yeni şeyler kullanmaktan kaçınırım. Örneğin, şimdi bile insanların anonim işlevleri kullanamayacakları kadar eski bir MATLAB sürümünü kullandıklarını görüyorum.


7
Evet, zekice, ancak ans değişkenine bir şey atarsanız yerel Matlab editörü bir uyarı verecektir. Uyarı almanın çok zarif olduğunu sanmıyorum ...
Jordi

11
Uyarıyı kapatabilirsiniz. Satırı bu açıklama dizesiyle sonlandırın% # ok Mlint bunu dikkate almaz. Uyarı yok.

13

İşte kullanabileceğiniz başka bir seçenek. Önce tüm çıktıları yakalamak için bir hücre dizisi oluşturun ( belirli bir işlevin kaç çıktı döndürdüğünü belirlemek için NARGOUT işlevini kullanabilirsiniz ):

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

Ardından işlevi aşağıdaki şekilde çağırın:

[a{:}] = func();

Ardından , istediğiniz bir öğeyi kaldırın ve a :

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

9

Bir kth çıkışı işlevi yazdım:


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

sonra arayabilirsin

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

işlevi de şu şekilde tamamlayabilirsiniz:

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

daha sonra kullanırsın

val_i_want = func_i_want(func_input_1,func_input_2);

Bunun gibi anonim işlevlerin kullanımıyla ilgili ek yükler olduğunu ve bunun kodda binlerce kez çağrılacak bir şey olmadığını unutmayın.


4

Matlab 2010a'da, istediğiniz şeyi yapmanın düzgün bir yolunu buldum. Basit değişken olarak "~" karakterini (elbette tırnak işaretleri olmadan) kukla değişken olarak kullanmaktır (birden fazla parametre döndürürken istediğiniz kadar). Bu ayrıca, işlevler eksik verileri işlemek üzere tasarlanmışsa, işlevlere girdi parametreleri için de çalışır. Bunun önceki sürümlerde var olup olmadığını bilmiyorum, ancak yakın zamanda karşılaştım.


11
Önceki cevabı görmedin mi?
yuk

1

Yalnızca seçilen çıktıları döndüren bir işlev (veya anonim işlev) yapabilirsiniz, örn.

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

Daha sonra fonksiyonunuzu şu şekilde çağırabilirsiniz:

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

Veya çıkışı bir değişkene atayabilirsiniz:

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

benim için çalışmıyor. Güvenilirdecimatedfftx = select(fft(x,12),1:4:12);
NotGaeL

1
select(func,2)aramalar func(2). Bunun çıktı argümanlarını seçtiği yeri göremiyorum.
Cris Luengo

0

Ans (n) kullanmamak için bunun gibi bir sebep var mı:

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

size(a);

b=ans(2);

B = 10 verir ve bu yol tüm Matlab sürümleriyle uyumlu olmaz mı?

Dahası, bu, kaç argüman olacağını bilmediğinizde ikinci çıktı argümanını elde etmeye çalışır! Oysa bunu yaparsanız:

[~, b] = size(a);

O halde b = 8000! (Daha fazla argüman yakalamak için ~ ile bitirmeniz gerekir!)


Bu yanıt, döndürülen değişkenin bir vektör olduğunu varsayar, bu muhtemelen OP'nin kastettiği şey değildir.
Neil Traft

Bu anlamlı değil. size(a)ve [b,c]=size(a)farklı şeyler iade edin. MATLAB'daki fonksiyonlar, çıktı argümanlarının sayısına bağlı olarak davranışı değiştirir.
Cris Luengo

Bu cevabı anlamakta zorlanıyorum. Bunun orijinal soruya doğrudan cevap vermemesi bir yana, buradaki cevapların kalitesine nasıl katkıda bulunduğunu bilmiyorum.
rayryeng

6 yıl sonra ve artık Matlab kullanmıyorum. Hatırladığım kadarıyla, "size ()" işlevi alakasızdı - ben sadece onu birden çok argüman döndürecek bir işlev olarak kullandım. Önemli olan, döndürülen n değişkeninin değerini elde etmek için basitçe func () ve sonra ans (n) çağırabilirim. Bu, belirli durumlarda iyi çalışıyor ve geriye dönük olarak uyumlu görünüyordu. Elbette sadece belirli işlevlerle veya değişken türlerle çalışabilir. Bu, 6 yıl sonra yardımcı olabileceğim kadar.
user1596274
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.