Как элегантно игнорировать некоторые возвращаемые значения функции MATLAB?

110

Можно ли получить возвращаемое значение "nth" из функции без необходимости создавать фиктивные переменные для всех возвращаемых значений 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;

Я все еще думаю, что это очень уродливый код, но если нет лучшего способа, я думаю, что я приму ответ.

  • 0
    Помимо использования массива ячеек, как я описал в своем ответе, повторение имени переменной, вероятно, ваше единственное другое решение. Надеюсь, ваши имена переменных не такие длинные, как "variableThatIWillUse". знак равно
  • 0
    На самом деле они есть. «Пустышка» была просто примером. Обычно я бы использовал 'variableThatIWillNotUse'. Другие переменные называются «variableThatIMightUse», «variableThatIWillUse2» и «variableThatCanBarelyFitOnA80CharacterLine». Я исследую корреляцию между длинными именами и рейтингами убийств. ;)
Показать ещё 3 комментария
Теги:
function
return-value

9 ответов

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, является третьим аргументом)


изменить: есть лучший подход; см. ManWithSleeve.

  • 7
    Не думал о решении этого, как это. Тем не менее, я чувствую, что это решение жертвует ясностью намерений ради хитрости.
  • 5
    Лично я просто использую [junk, junk, c] = function_call () и предполагаю, что «мусор» никогда не является важной переменной, и если он содержит много памяти, я очищу его при необходимости.
Показать ещё 4 комментария
216

В MATLAB версии 7.9 (R2009b) вы можете использовать ~, например,

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

Обратите внимание, что , не является необязательным. Просто набрав [~ ~ var], он не будет работать и выдает ошибку.

Подробнее см. примечания к выпуску.

  • 3
    Раздражает, что это не "_". (Полагаю, это уже было взято?)
  • 4
    @SamB: хотя использование оператора not как don't care , тоже не так уж плохо
Показать ещё 3 комментария
35

Если вы хотите использовать стиль, в котором переменная будет оставлена, чтобы упасть в ведро бит, разумной альтернативой является

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

ans - это, конечно, стандартная мусорная переменная для matlab, которая часто перезаписывается в ходе сеанса.

В то время как мне нравится новый трюк, который MATLAB теперь разрешает, используя символ ~ для обозначения игнорируемой возвращаемой переменной, это проблема для обратной совместимости, поскольку пользователи более старых версий не смогут использовать ваш код. Обычно я избегаю использовать такие новые вещи, пока не выпустят хотя бы несколько выпусков MATLAB, чтобы обеспечить очень мало пользователей, оставшихся в беде. Например, даже сейчас я нахожу, что люди все еще используют достаточно старый выпуск MATLAB, который не может использовать анонимные функции.

  • 7
    Да, это умно, но собственный редактор Matlab выдаст предупреждение, если вы назначите что-нибудь для переменной ans. Я не думаю, что предупреждения очень элегантны ...
  • 11
    Вы можете отключить предупреждение. Завершите строку этой строкой комментария% # ok. Mlint проигнорирует это. Нет предупреждений.
12

Вот еще один вариант, который вы можете использовать. Сначала сделайте массив ячеек для захвата всех выходов (вы можете использовать функцию 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:

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
    Разве вы не видели предыдущий ответ?
3

Вы можете создать функцию (или анонимную функцию), которая возвращает только выбранные выходы, например

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

Затем вы можете вызвать свою функцию следующим образом:

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

Или вы можете назначить вывод переменной:

output(1,2:4) = select(func,1:3);
  • 0
    не работает для меня Пробовал decimatedfftx = select(fft(x,12),1:4:12);
  • 1
    select(func,2) вызывает func(2) . Я не вижу, где это выбирает выходные аргументы.
2

Есть ли причина не использовать ans (n), например:

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

size(a);

b=ans(2);

Дает b = 10, и будет ли этот способ не совместим со всеми версиями Matlab?

Кроме того, это работает, чтобы получить второй выходной аргумент, когда вы не знаете, сколько аргументов будет! Если вы это сделаете:

[~, b] = size(a);

Тогда b = 8000! (Вам нужно закончить с ~, чтобы уловить больше аргументов!)

  • 0
    В этом ответе предполагается, что возвращаемая переменная является вектором, который, вероятно, не имел в виду OP.
  • 0
    Это не имеет никакого смысла. size(a) и [b,c]=size(a) возвращают разные вещи. Функции в MATLAB изменяют поведение в зависимости от количества выходных аргументов.
Показать ещё 2 комментария
-2

Я обнаружил, что если вам нужен только один вывод, вы можете пересечь функцию с матрицей единиц измерения, соответствующую желаемому выходу. т.е. out_arg_the_third = функция (input_args) * [0; 0; 1; 0];

или усложняясь, вы можете расширить размеры своей матрицы, чтобы собрать больше результатов: out_arg_second_and_third = функция (input_args) * [0,0; 1,0; 0,1; 0,0]; но мы начинаем терять элегантность здесь.

Должны быть лучшие способы с более новыми версиями, но по причинам, которые я не понимаю, мне нужно использовать 2007b

Ещё вопросы

Сообщество Overcoder
Наверх
Меню