web-dev-qa-db-ja.com

VBAのIIFのようにインラインに配置できるMatlabの条件付きIF演算子はありますか

VBAでは、次のことができます。

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

c> 0の場合、A=B+CおよびC <= 0を取得A=B

MATLABコードでこれらの条件inlineを実行できる演算子または関数はありますか?

27
Lance Roberts

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;
_

より高度なソリューションとして、 匿名関数shenanigansについてのこのブログ投稿 に概説されているように、elseifを実行できるインライン関数を作成する方法があります。

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

この関数は次のように使用します

_iif(condition_1,value_1,...,true,value_final)
_

ここで、ドットを任意の数の追加の条件/値のペアで置き換えます。

これが機能する方法は、値の中から条件が真である最初の値を選択することです。 2*find(),1,'first')は、値引数へのインデックスを提供します。

26
Jonas

操作で必要なときにMATLABが変数タイプを自動的に変換するという事実を単純に使用してみてはどうでしょうか?例えば、論理的から二重へ。

変数がスカラーdoubleの場合、コードは次のように置き換えられると思います

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

この場合、演算子(c > 0)1(論理型)は常にc > 0であり、そうでない場合は0の値です。

34
Alex

他の人たちは、Matlabには三項演算子?:がないことをすでに言っています。解決策として、値の代わりに3つの関数を取るこの関数をお勧めします。したがって、不要な計算の量は最小限に抑えられ、条件を確認できますbefore計算を開始します。値が実際に数値、有限、またはゼロ以外の場合:

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))
6
quazgar

これには組み込みのソリューションはありませんが、 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
6
kol

Jonasの答えに触発されて、以下の関数は混合型の入力と文字に対しても機能しますが、彼の関数は安定していません。

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

編集:セルブランチの余分な条件オプションを削除しました。これは明らかに以前の間違いの残骸でしたが、これはおそらくより高速で、間違いなくクリーンです。

3
hugovdberg

MathWorksファイル交換にtern関数が追加されました。 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
1
Alex

これは、アレックスの答えに対する補足です。

infを返したい場合、Alexのメソッドは機能しません

これらの場合、しばしば0*inf図。MATLABはNaNに評価します。問題がある...代わりにルックアップを使用して、この乗算を回避できます。

例として、凸最適化における有用なバリア関数は、logがどこでも正であり、-inf他の場所。ルックアップを使用してこのような関数を作成する方法を次に示します。

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

インライン条件はハックであり、遅延評価を失います。あなたは注意する必要があります。ただし、セマンティックコードを持つことは本当に素晴らしいことであり、全員の環境が同じであることを保証できない場合にコードを共有する方が簡単です。

1
enthdegree

関数の作成を強制せず、かなり単純な式を処理できるオプションを探している場合は、匿名関数を利用できます。無名関数は、数値1または0の論理値を返します。このため、他の数値と乗算して、式の後に値を保持するか、値を失うかを判断できます。

あなたの場合(A、B、Cがベクトルかどうかを含む):A = B .+ (@() C>0)()

0
TheBrenny