wake-up-neo.com

Gibt es einen bedingten IF-Operator von Matlab, der wie der IIF von VBA INLINE platziert werden kann

In VBA kann ich Folgendes tun:

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

so dass, wenn C> 0 ich A=B+C und C <= 0 bekomme ich A=B

Gibt es einen Operator oder eine Funktion, die diese Bedingungen Inline in MATLAB-Code ausführen lässt?

27
Lance Roberts

In Matlab gibt es keinen ternären Operator. Sie können natürlich eine Funktion schreiben, die dies tun würde. Die folgende Funktion arbeitet beispielsweise als iif mit n-d-Eingabe für die Bedingung und mit Zahlen und Zellen für die Ergebnisse a und b:

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

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

out(cond) = a;

Für eine fortschrittlichere Lösung gibt es eine Möglichkeit, eine Inline-Funktion zu erstellen, die sogar andere Funktionen ausführen kann, wie in diesem Blogpost über die anonyme Funktion shenanigans beschrieben:

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

Sie verwenden diese Funktion als

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

wo Sie die Punkte durch eine beliebige Anzahl zusätzlicher Paare aus Bedingung/Wert ersetzen.

Das funktioniert so, dass der erste Wert unter den Werten ausgewählt wird, dessen Bedingung wahr ist. 2*find(),1,'first') stellt den Index für die Wertargumente bereit.

26
Jonas

Wie wäre es, wenn Sie einfach die Tatsache nutzen, dass MATLAB Variablentypen automatisch konvertiert, wenn dies für die Operation erforderlich ist? Zum Beispiel logisch zu verdoppeln.

Wenn Ihre Variablen doppelt skaliert sind, kann Ihr Code, glaube ich, durch ersetzt werden

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

In diesem Fall legt der Operator (c > 0) Werte 1 (logischer Typ) fest, wenn c > 0 und ansonsten 0.

33
Alex

Andere haben bereits gesagt, dass es in Matlab keinen ternären ?:-Operator gibt. Als Lösung schlage ich diese Funktion vor, die drei Funktionen anstelle von Werten übernimmt. Daher wird die Anzahl unnötiger Berechnungen minimiert und Sie können die Bedingungen vor Startberechnungen prüfen, z. Wenn ein Wert wirklich numerisch oder endlich oder ungleich Null ist:

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

Verwenden Sie es so:

f = @(y)(iif(@(x)(x > 3), @(x)(x.^2), @(x)(x/2), y))
f(linspace(0,6,10))
6
quazgar

Es gibt keine integrierte Lösung dafür, aber Sie können schreiben Sie selbst 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

Inspiriert durch Jonas 'Antwort funktioniert die Funktion unten auch für gemischte Texteingaben und Zeichen, für die seine Funktion nicht stabil ist.

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

Edit : Die zusätzlichen bedingten Optionen im Zellzweig wurden ausgesondert, die anscheinend Reste eines vorherigen Fehlers waren. Dies ist wahrscheinlich schneller und definitiv sauberer.

3
hugovdberg

Es gibt jetzt eine tern-Funktion für den MathWorks-Dateiaustausch: http://www.mathworks.com/matlabcentral/fileexchange/39735-functional-programming-constructs/content/tern.m

Der Code wird hier wiedergegeben:

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

Dies ist eher ein Addenum zu Alex 'Antwort. 

Alexs Methode funktioniert nicht, wenn Sie inf zurückgeben möchten

In diesen Fällen erhalten Sie häufig eine 0*inf-Zahl, die MATLAB als NaN auswertet. Problematisch ... Wir können diese Multiplikation stattdessen durch eine Suche vermeiden.

Eine nützliche Barrierefunktion bei der konvexen Optimierung verhält sich beispielsweise wie log überall positiv und -inf an anderer Stelle. So erstellen Sie eine solche Funktion mithilfe einer Suche:

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

Inline-Bedingungen sind ein Hack, und Sie verlieren die faule Bewertung. Du musst vorsichtig sein. Allerdings ist semantischer Code wirklich schön und es ist einfacher, Ihren Code gemeinsam zu nutzen, wenn Sie nicht garantieren können, dass alle Umgebungen gleich sind.

1
enthdegree

Wenn Sie nach einer Option suchen, die Sie nicht zum Erstellen einer Funktion zwingt und relativ einfache Ausdrücke verarbeiten kann, können Sie anonyme Funktionen nutzen. Die anonyme Funktion gibt eine logische Zahl zurück, die 1 oder 0 sein kann. Aus diesem Grund können sie zum Multiplizieren mit anderen Zahlen verwendet werden, um festzustellen, ob sie nach dem Ausdruck noch einen Wert enthalten oder ihren Wert verlieren.

Für Ihren Fall (einschließlich, ob A, B und C Vektoren sind oder nicht): A = B .+ (@() C>0)()

0
TheBrenny