Есть ли в Matlab условный оператор IF, который можно поместить INLINE, как VBA IIF

26

В VBA я могу сделать следующее:

A = B + IIF(C>0, C, 0)

так что если C > 0, то получим A=B+C и C <= 0 получаем A=B

Есть ли оператор или функция, которые позволят мне выполнять эти условные обозначения inline в коде MATLAB?

  • 1
    возможный дубликат условного присвоения Matlab
  • 1
    @ Тим Уильямс, нет, я ищу INLINE.
Показать ещё 4 комментария
Теги:
ternary-operator
iif
conditional-operator

7 ответов

22
Лучший ответ

В Matlab нет тройного оператора. Вы можете, конечно, написать функцию, которая сделает это. Например, следующая функция работает как iif с входом n-d для условия и с числами и ячейками для результатов a и b:

function out = iif(cond,a,b)
%IIF implements a ternary operator

% pre-assign out
out = repmat(b,size(cond));

out(cond) = a;

Для более продвинутого решения существует способ создания встроенной функции, которая может даже делать elseif, как указано в этом сообщении в блоге об анонимной функции shenanigans:

iif  = @(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();

Вы используете эту функцию как

iif(condition_1,value_1,...,true,value_final)

где вы заменяете точки любым количеством дополнительных пар условий/значений.

Как это работает, так это то, что он выбирает среди значений, первое из которых условие истинно. 2*find(),1,'first') предоставляет индекс в аргументы значения.

  • 0
    @EitanT: Да, это действительно хорошо работает, когда вы можете умножить (хотя вы можете использовать круглые скобки вокруг ~cond ). Тем не менее, другой ответ уже упоминал об этом, поэтому я не хотел повторять другой ответ.
29

Как просто использовать тот факт, что MATLAB автоматически преобразует типы переменных, когда требуется операция? Например, логическое удвоение.

Если ваши переменные являются скалярными, ваш код, я считаю, можно заменить на

a = b + (c > 0) * c;

В этом случае оператор (c > 0) значения 1 (логический тип) всякий раз, когда c > 0 и значения в 0 в противном случае.

  • 0
    +1 молодец, спасибо
  • 0
    Вы можете даже использовать это, определив iif = @(c,t,f) c.*(tf) + f , так что вы можете даже делать вещи векторизованными. Я думаю, что ваш ответ - лучшее решение MATLAB для простого использования.
Показать ещё 1 комментарий
6
Другие говорили уже, что нет тройного оператора ?: в Matlab. В качестве решения я предлагаю эту функцию, которая вместо трех значений использует три функции. Поэтому количество ненужных вычислений минимизируется, и вы можете проверить условия до начала расчетов, например. если значение действительно числовое или конечное или ненулевое:
function [ out ] = iif( condition, thenF, elseF, in, out)
%iif Implements the ternary ?: operator
%   out = iif (@condition, @thenF, @elseF, in[, out])
%
%   The result is equivalent to:
%   condition(x) ? thenF(x) : elseF(x)
%
%   The optional argument out serves as a template, if the output type is
%   different from the input type, e.g. for mapping arrays to cells and
%   vice versa.
%
% This code is in the public domain.

mask = condition(in);
if nargin <= 4
  out = in;
end

if sum(mask)
  out(mask)  = thenF(in(mask));
end
if sum(~mask)
  out(~mask) = elseF(in(~mask));
end

end

Используйте его следующим образом:

f = @(y)(iif(@(x)(x > 3), @(x)(x.^2), @(x)(x/2), y))
f(linspace(0,6,10))
  • 1
    Это лучшее приближение к C ?, который не оценивает ветвь, которая не берется. К сожалению, синтаксис Мех.
6

Для этого нет встроенного решения, но вы можете написать сам IIF.

function result=iif(cond, t, f)
%IIF - Conditional function that returns T or F, depending of condition COND
%
%  Detailed 
%     Conditional matrix or scalar double function that returns a matrix
%     of same size than COND, with T or F depending of COND boolean evaluation
%     if T or/and F has the same dimensions than COND, it uses the corresponding 
%     element in the assignment
%     if COND is scalar, returns T or F in according with COND evaluation, 
%     even if T or F is matrices like char array.
%
%  Syntax
%    Result = iif(COND, T, F)
%           COND - Matrix or scalar condition
%           T  - expression if COND is true
%           F  - expression if COND is false
%           Result - Matrix or scalar of same dimensions than COND, containing
%                    T if COND element is true or F if COND element is false.
%
if isscalar(cond) 
   if cond 
       result = t;
   else
       result = f;
   end
else
  result = (cond).*t + (~cond).*f;
end  
end
  • 0
    Векторная версия неправильно обрабатывает NaN
3

Вдохновленный ответом Джонаса, функция ниже также работает для ввода смешанного типа и символов, для которых его функция нестабильна.

function out = iif(cond, a, b)
%IIF implements a ternary operator

    % Use cell output for either char or mixed type input
    if ischar(a) || ischar(b) || ~strcmp(class(a), class(b))
        out = cell(size(cond));
        [out{cond}] = deal(a);
        [out{~cond}] = deal(b);
    else
        % Use array output and logical indexing
        out = repmat(b, size(cond));
        out(cond) = a;
    end
end

Изменить: отсечены дополнительные условные параметры в ветки ячейки, которые были, по-видимому, остатками предыдущей ошибки, вероятно, быстрее и определенно чище.

1

Это скорее адденум для ответа Алекса.

Метод Alex не работает, если вы хотите вернуть inf

В этих случаях вы часто получаете цифру 0*inf, которую MATLAB будет оценивать до NaN. Проблематично... Мы можем избежать этого умножения, используя поиск.

В качестве примера полезной барьерной функцией в выпуклой оптимизации является то, что ведет себя как log везде положительно, а -inf в другом месте. Вот как вы можете создать такую ​​функцию с помощью поиска:

INF_CONDITION = [0, inf];
fn_logbr = @(x) (x>0)*log(x) - INF_CONDITION( 1+(x<=0) )

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

1

Теперь существует функция tern в обмене файлами MathWorks: http://www.mathworks.com/matlabcentral/fileexchange/39735-functional-programming-constructs/content/tern.m

Здесь воспроизводится код:

function varargout = tern(condition, true_action, false_action)

% out = tern(condition, true_action, false_action)
% 
% Ternary operator. If the first input is true, it returns the second
% input. Otherwise, it returns the third input. This is useful for writing
% compact functions and especially anonymous functions. Note that, like
% many other languages, if the condition is true, not only is the false
% condition not returned, it isn't even executed. Likewise, if the
% condition is false, the true action is never executed. The second and
% third arguments can therefore be function handles or values.
%
% Example:
%
% >> tern(rand < 0.5, @() fprintf('hi\n'), pi)
% ans =
%     3.1416
% >> tern(rand < 0.5, @() fprintf('hi\n'), pi)
% hi
%
% It works with multiple outputs as well.
%
% >> [min_or_max, index] = tern(rand < 0.5, ...
%                               @() min([4 3 5]), ...
%                               @() max([4 3 5]))
% min_or_max =
%      5
% index =
%      3
%
% Tucker McClure
% Copyright 2013 The MathWorks, Inc.

    if condition() % Works for either a value or function handle.
        [varargout{1:nargout}] = true_action();
    else
        [varargout{1:nargout}] = false_action();
    end

end

Ещё вопросы

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