จะเพิกเฉยต่อค่าส่งคืนบางค่าของฟังก์ชัน MATLAB ได้อย่างไร?


120

เป็นไปได้หรือไม่ที่จะได้รับค่าส่งคืน 'ที่ n' จากฟังก์ชันโดยไม่ต้องสร้างตัวแปรจำลองสำหรับn-1ค่าที่ส่งคืนทั้งหมดก่อนหน้านั้น

สมมติว่าฉันมีฟังก์ชันต่อไปนี้ใน MATLAB:

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

ตอนนี้สมมติว่าฉันสนใจเฉพาะค่าตอบแทนที่สามเท่านั้น สิ่งนี้สามารถทำได้โดยการสร้างตัวแปรจำลองหนึ่งตัว:

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

แต่ผมคิดว่านี่เป็นชนิดของน่าเกลียด ฉันคิดว่าคุณอาจจะทำสิ่งใดสิ่งหนึ่งต่อไปนี้ได้ แต่คุณทำไม่ได้:

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

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

จะมีผู้ใดที่สง่างามวิธีการที่จะทำเช่นนี้ที่จะทำงานหรือไม่


จนถึงตอนนี้ทางออกที่ดีที่สุดคือใช้variableThatIWillUseเป็นตัวแปรดัมมี่ สิ่งนี้ช่วยให้ฉันไม่ต้องสร้างตัวแปรจำลองจริงที่ก่อให้เกิดมลพิษในพื้นที่ทำงาน (หรือฉันต้องล้าง) กล่าวโดยย่อ: วิธีแก้ปัญหาคือใช้variableThatIWillUseสำหรับทุกค่าที่ส่งคืนจนถึงค่าที่น่าสนใจ ส่งคืนค่าหลังจากสามารถละเว้นได้:

[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;

ฉันยังคิดว่านี่เป็นรหัสที่น่าเกลียดมาก แต่ถ้าไม่มีวิธีที่ดีกว่านี้ฉันเดาว่าฉันจะยอมรับคำตอบ


นอกเหนือจากการใช้อาร์เรย์เซลล์ตามที่ฉันอธิบายไว้ในคำตอบของฉันการทำซ้ำชื่อตัวแปรอาจเป็นวิธีแก้ปัญหาอื่น ๆ ของคุณ หวังว่าชื่อตัวแปรของคุณจะไม่ยาวเท่ากับ "variableThatIWillUse" =)
gnovice

จริงๆแล้วพวกเขา 'หุ่น' เป็นเพียงตัวอย่างเท่านั้น โดยปกติฉันจะใช้ 'variableThatIWillNotUse' ตัวแปรอื่นมีชื่อว่า 'variableThatIMightUse', 'variableThatIWillUse2' และ 'variableThatCanBarelyFitOnA80CharacterLine' ฉันกำลังค้นคว้าความสัมพันธ์ระหว่างชื่อยาวและการจัดอันดับคดีฆาตกรรม ;)
Jordi

26
อันที่จริงแล้วเนื่องจาก R2009b เพิกเฉยต่อการคืนค่าฟังก์ชันได้รับการแก้ไขอย่างหรูหรายิ่งขึ้นโดยใช้ '~' -Char เช่น: [~, b] = sort (rand (10,1))
ymihere

1
สำหรับผู้อ่านใหม่: ^ ควรเป็นคำตอบที่ถูกต้อง ดูคำตอบของ ManWithSleeveด้านล่าง
A.

1
ในตัวอย่างของคุณหากคุณต้องการเพียงอาร์กิวเมนต์เอาต์พุตที่ 3 คุณจะต้องใช้: [variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func; ไม่จำเป็นต้องล้างตัวแปรดัมมี่ สำหรับ MATLAB เวอร์ชันใหม่กว่า> = R2009b ให้ใช้ [~, ~, variableThatIWillUse] = func;
Thierry Dalon

คำตอบ:


38

นี่เป็นการแฮ็กบ้าง แต่ใช้งานได้:

ก่อนอื่นฟังก์ชั่นตัวอย่างด่วน:

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

ตอนนี้สิ่งสำคัญคือถ้าคุณใช้ตัวแปรสองครั้งที่ด้านซ้ายมือของการกำหนดหลายนิพจน์การมอบหมายก่อนหน้านี้จะถูกรวมกลุ่มโดยการมอบหมายในภายหลัง:

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

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

(แก้ไข: เพื่อตรวจสอบฉันยังยืนยันว่าเทคนิคนี้ใช้ได้ผล[mu,mu,mu]=polyfit(x,y,n)หากสิ่งที่คุณสนใจpolyfitคืออาร์กิวเมนต์ที่ 3)


แก้ไข: มีแนวทางที่ดีกว่า ดูคำตอบของ ManWithSleeveแทน


7
ไม่เคยคิดจะแก้แบบนี้ อย่างไรก็ตามฉันรู้สึกว่าโซลูชันนี้เสียสละความชัดเจนของเจตนาเพื่อความชาญฉลาด
Jukka Dahlbom

5
โดยส่วนตัวแล้วฉันใช้ [junk, junk, c] = function_call () และถือว่าทั้งสองอย่างนั้น "ขยะ" ไม่เคยเป็นตัวแปรที่สำคัญและหากมีหน่วยความจำจำนวนมากฉันจะล้างมันหากจำเป็น
Jason S

5
ถึงผู้ลงคะแนน: ทำไมต้อง -1? คำตอบนี้เขียนขึ้นก่อนที่ R2009b จะออกด้วยซ้ำดังนั้นคำตอบของ @ ManWithSleeve จะไม่ได้ผลในเวลานั้น แน่นอนว่าเป็นแนวทางที่ถูกต้องแล้ว
Jason S

2
บางทีความคิดเห็นในบรรทัดแรกของคำตอบของคุณอาจเป็นประโยชน์? ฉันเพิ่งมาที่นี่ผ่าน Google ดังนั้นดูเหมือนว่ามันคุ้มค่าที่จะอัปเดต
FvD

การมอบหมายแบบซ้ายไปขวาไม่ได้รับการรับรองอย่างเป็นทางการจาก The MathWorks ดังนั้นคุณจึงไม่ควรพึ่งพาการใช้ c หลัง [c, c, c] = myFunc () (ดูความเห็น # 26 ที่นี่: blogs.mathworks.com/loren/2009/09/11/… )
Matt Krause

226

ด้วย MATLAB เวอร์ชัน 7.9 (R2009b) คุณสามารถใช้ ~ เช่น

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

โปรดทราบว่า,ไม่ใช่ทางเลือก เพียงแค่พิมพ์[~ ~ var]จะไม่ทำงานและจะทำให้เกิดข้อผิดพลาด

ดูรายละเอียดในบันทึกประจำรุ่น


3
น่ารำคาญที่ไม่ใช่ "_" (ฉันคิดว่าถ่ายไปแล้ว?)
SamB

4
@SamB: แม้ว่าการใช้notโอเปอเรเตอร์เหมือนเดิมdon't careก็ไม่เลวเช่นกัน
Tobias Kienzler

28
โปรดทราบว่า,ไม่ใช่ทางเลือก เพียงแค่พิมพ์[~ ~ var]จะไม่ทำงานและจะทำให้เกิดข้อผิดพลาด
eykanal

ฉันจะบอกว่านี่คือคำตอบที่ "ถูกต้อง" อีกอันเป็นเพียงการแฮ็กเพื่อแก้ไขปัญหาที่ไม่มีอยู่จริง ไม่ต้องเล่นสำนวน ...
patrik

6
คำถามถูกตั้งขึ้นในปี 2009 ก่อน R2009b ซึ่งในเวลานั้น ~ ไม่ได้ผล
Tom Anderson

37

หากคุณต้องการใช้สไตล์ที่ตัวแปรจะถูกปล่อยให้ตกอยู่ในที่เก็บข้อมูลบิตทางเลือกที่สมเหตุสมผลก็คือ

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

แน่นอนว่า ans เป็นตัวแปรขยะเริ่มต้นสำหรับ matlab ซึ่งมักจะถูกเขียนทับในระหว่างเซสชัน

ในขณะที่ฉันชอบเคล็ดลับใหม่ที่ MATLAB อนุญาตในตอนนี้โดยใช้ ~ เพื่อกำหนดตัวแปรผลตอบแทนที่ถูกเพิกเฉย แต่นี่เป็นปัญหาสำหรับความเข้ากันได้แบบย้อนหลังเนื่องจากผู้ใช้รุ่นเก่าจะไม่สามารถใช้รหัสของคุณได้ โดยทั่วไปฉันจะหลีกเลี่ยงการใช้สิ่งใหม่ ๆ เช่นนั้นจนกว่าจะมีการออก MATLAB อย่างน้อยสองสามรุ่นเพื่อให้แน่ใจว่าจะมีผู้ใช้น้อยมากที่เหลืออยู่ ตัวอย่างเช่นตอนนี้ฉันพบว่าผู้คนยังคงใช้ MATLAB รุ่นเก่าพอที่พวกเขาไม่สามารถใช้ฟังก์ชันที่ไม่ระบุชื่อได้


7
ใช่มันฉลาด แต่ตัวแก้ไข Matlab ดั้งเดิมจะเตือนถ้าคุณกำหนดอะไรให้กับตัวแปร ans ฉันไม่คิดว่าการมีคำเตือนจะสวยหรูมาก ...
Jordi

11
คุณสามารถปิดคำเตือนได้ จบบรรทัดด้วยสตริงความคิดเห็นนี้% # ok Mlint จะไม่สนใจสิ่งนี้ ไม่มีคำเตือน

13

นี่เป็นอีกทางเลือกหนึ่งที่คุณสามารถใช้ได้ ขั้นแรกให้สร้างอาร์เรย์เซลล์เพื่อจับเอาท์พุททั้งหมด (คุณสามารถใช้ฟังก์ชันNARGOUTเพื่อกำหนดจำนวนเอาต์พุตที่ฟังก์ชันที่กำหนดจะส่งกลับ):

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

จากนั้นเรียกใช้ฟังก์ชันดังนี้:

[a{:}] = func();

แล้วก็ลบองค์ประกอบจากที่คุณต้องการและเขียนทับ:

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

9

ฉันเขียนฟังก์ชัน 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

จากนั้นคุณสามารถโทร

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

คุณยังสามารถสรุปฟังก์ชันเช่น

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

หลังจากนั้นคุณใช้

val_i_want = func_i_want(func_input_1,func_input_2);

โปรดทราบว่ามีค่าใช้จ่ายที่เกี่ยวข้องกับการใช้ฟังก์ชันที่ไม่ระบุตัวตนเช่นนี้และนี่ไม่ใช่สิ่งที่ฉันจะทำในรหัสที่เรียกว่าหลายพันครั้ง


4

ใน Matlab 2010a ฉันพบวิธีที่เรียบร้อยในการทำสิ่งที่คุณขอ เพียงแค่ใช้ characher "~" (โดยไม่มีเครื่องหมายอัญประกาศ) เป็นตัวแปรจำลองของคุณ (มากเท่าที่คุณต้องการเมื่อส่งคืนพารามิเตอร์หลายตัว) นอกจากนี้ยังใช้ได้กับพารามิเตอร์อินพุตไปยังฟังก์ชันหากฟังก์ชันได้รับการออกแบบมาเพื่อจัดการกับข้อมูลที่ขาดหายไป ฉันไม่รู้ว่าสิ่งนี้มีอยู่ในเวอร์ชันก่อนหน้านี้หรือไม่ แต่ฉันเพิ่งเจอเมื่อไม่นานมานี้


11
คุณไม่เห็นคำตอบก่อนหน้านี้หรือไม่?
yuk

1

คุณสามารถสร้างฟังก์ชัน (หรือฟังก์ชันที่ไม่ระบุตัวตน) ที่ส่งคืนเฉพาะเอาต์พุตที่เลือกเช่น

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

จากนั้นคุณสามารถเรียกใช้ฟังก์ชันของคุณดังนี้:

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

หรือคุณสามารถกำหนดผลลัพธ์ให้กับตัวแปร:

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

ไม่ได้ผลสำหรับฉัน Trieddecimatedfftx = select(fft(x,12),1:4:12);
NotGaeL

1
select(func,2)โทรfunc(2). ฉันไม่เห็นว่าสิ่งนี้เลือกอาร์กิวเมนต์เอาต์พุตที่ไหน
Cris Luengo

0

มีเหตุผลใดบ้างที่จะไม่ใช้ ans (n) เช่นนี้:

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

size(a);

b=ans(2);

ให้ b = 10 และวิธีนี้จะเข้ากันไม่ได้กับ Matlab ทุกเวอร์ชันหรือไม่?

นอกจากนี้ยังใช้เพื่อรับอาร์กิวเมนต์เอาต์พุตที่สองเมื่อคุณไม่รู้ว่าจะมีอาร์กิวเมนต์กี่ข้อ! ในขณะที่หากคุณทำสิ่งนี้:

[~, b] = size(a);

แล้ว b = 8000! (คุณต้องลงท้ายด้วย ~ เพื่อให้ได้ข้อโต้แย้งมากขึ้น!)


คำตอบนี้ถือว่าตัวแปรที่ส่งกลับเป็นเวกเตอร์ซึ่งอาจไม่ใช่สิ่งที่ OP หมายถึง
Neil Traft

สิ่งนี้ไม่สมเหตุสมผล size(a)และ[b,c]=size(a)คืนสิ่งที่แตกต่าง ฟังก์ชันใน MATLAB เปลี่ยนพฤติกรรมตามจำนวนอาร์กิวเมนต์เอาต์พุต
Cris Luengo

ฉันมีปัญหาในการทำความเข้าใจกับคำตอบนี้ ฉันไม่รู้ว่าสิ่งนี้ก่อให้เกิดคุณภาพของคำตอบที่นี่ได้อย่างไรนับประสาที่สิ่งนี้ไม่ได้ตอบคำถามเดิมโดยตรง
rayryeng

6 ปีต่อมาและฉันไม่ได้ใช้ Matlab อีกต่อไป เท่าที่ฉันจำได้ฟังก์ชัน "size ()" ไม่เกี่ยวข้อง - ฉันแค่ใช้เป็นฟังก์ชันที่จะส่งคืนอาร์กิวเมนต์หลายรายการ ประเด็นก็คือฉันสามารถเรียก func () จากนั้น ans (n) เพื่อรับค่าของตัวแปรที่ส่งคืนจำนวน n ดูเหมือนว่าจะทำงานได้ดีในบางสถานการณ์และเข้ากันได้แบบย้อนกลับ อาจใช้ได้เฉพาะกับฟังก์ชันบางอย่างแน่นอนหรือตัวแปรประเภทใดก็ได้ นั่นเท่าที่ฉันสามารถช่วยได้ 6 ปีต่อมา
user1596274
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.