Wie wird der bedingte Operator (? :
) in Ruby verwendet?
Ist dies beispielsweise richtig?
<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Es ist der ternäre Operator und funktioniert wie in C (die Klammern sind nicht erforderlich). Es ist ein Ausdruck, der wie folgt funktioniert:
if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this
In Ruby ist if
jedoch auch ein Ausdruck, also: if a then b else c end
=== a ? b : c
, mit Ausnahme von Prioritätsproblemen. Beides sind Ausdrücke.
Beispiele:
puts (if 1 then 2 else 3 end) # => 2
puts 1 ? 2 : 3 # => 2
x = if 1 then 2 else 3 end
puts x # => 2
Beachten Sie, dass im ersten Fall Klammern erforderlich sind (andernfalls ist Ruby verwirrt, weil er der Meinung ist, dass es puts if 1
mit etwas zusätzlichem Müll ist), aber im letzten Fall sind sie nicht erforderlich, da das Problem nicht auftritt.
Sie können das "long-if" -Formular für die Lesbarkeit in mehreren Zeilen verwenden:
question = if question.size > 20 then
question.slice(0, 20) + "..."
else
question
end
puts true ? "true" : "false"
=> "true"
puts false ? "true" : "false"
=> "false"
Ihre Verwendung von ERB legt nahe, dass Sie sich in Rails befinden. Wenn ja, dann betrachten Sie truncate
, einen integrierten Helfer, der die Arbeit für Sie erledigt:
<% question = truncate(question, :length=>30) %>
@pst gab eine großartige Antwort, aber ich möchte erwähnen, dass in Ruby der ternäre Operator in eine Zeile geschrieben wird, um syntaktisch korrekt zu sein, im Gegensatz zu Perl und C, wo wir ihn in mehrere Zeilen schreiben können:
(true) ? 1 : 0
Normalerweise gibt Ruby einen Fehler aus, wenn Sie versuchen, es auf mehrere Zeilen aufzuteilen. Sie können jedoch das \
-Zeilenfortsetzungssymbol am Ende einer Zeile verwenden. Ruby ist zufrieden:
(true) \
? 1 \
: 0
Dies ist ein einfaches Beispiel, aber es kann sehr nützlich sein, wenn Sie mit längeren Zeilen arbeiten, da der Code schön angeordnet ist.
Es ist auch möglich, das Ternary ohne die Zeilenfortsetzungszeichen zu verwenden, indem die Operatoren als letzte Zeile in der Zeile stehen, aber ich mag oder empfehle es nicht:
(true) ?
1 :
0
Ich denke, das führt zu wirklich schwer zu lesendem Code, da der bedingte Test und/oder die Ergebnisse länger werden.
Ich habe Kommentare gelesen, die besagen, dass der ternäre Operator nicht verwendet werden sollte, weil er verwirrend ist. Nach der gleichen Logik sollten wir keine regulären Ausdrücke, Bereichsoperatoren ('..
' und die scheinbar unbekannte "Flip-Flop-Variante") verwenden. Sie sind mächtig, wenn sie richtig eingesetzt werden. Daher sollten wir lernen, sie richtig anzuwenden.
Warum haben Sie Klammern um
true
gesetzt?
Betrachten Sie das Beispiel des OP:
<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Das Umschließen des Bedingungs-Tests trägt dazu bei, den Test lesbarer zu machen, da er den Test visuell trennt:
<% question = (question.size > 20) ? question.question.slice(0, 20)+"..." : question.question %>
Natürlich kann das gesamte Beispiel durch die Verwendung einiger sinnvoller Whitespace-Erweiterungen deutlich lesbarer gemacht werden. Dies ist nicht getestet, aber Sie bekommen die Idee:
<% question = (question.size > 20) ? question.question.slice(0, 20) + "..." \
: question.question
%>
Oder idiomatischer geschrieben:
<% question = if (question.size > 20)
question.question.slice(0, 20) + "..."
else
question.question
end
%>
Es ist leicht zu argumentieren, dass die Lesbarkeit auch unter question.question
leidet.
Ein einfaches Beispiel, bei dem der Bediener überprüft, ob die ID des Spielers 1 ist, und abhängig vom Ergebnis die Feind-ID festlegt
player_id=1
....
player_id==1? enemy_id=2 : enemy_id=1
# => enemy=2
Und ich habe ein post zu dem Thema gefunden, was ziemlich hilfreich erscheint.
Eine kleine Variante davon ist die Konvertierung in Boolean !! Betreiber wie dieser
result = !!(condition == true)
Der Code condition ? statement_A : statement_B
ist äquivalent zu
if condition == true
statement_A
else
statement_B
end