Come si usa l'operatore condizionale (? :) in Ruby?


303

Come viene utilizzato l'operatore condizionale ( ? :) in Ruby?

Ad esempio, è corretto?

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

1
sì, penso, ma penso anche che potresti riuscirci: question=question[0,20] se fosse inferiore a 20, non cambierà nulla.
DGM,

ho anche bisogno di aggiungere un '...' se la lunghezza è maggiore di 20
Mithun Sreedharan,

1
Fai attenzione a tagliare ciecamente una linea in corrispondenza di una determinata colonna. Puoi finire per tagliare una parola a metà strada quindi aggiungere i puntini di sospensione ('...'), che sembra male. Cerca invece un segno di punteggiatura o uno spazio bianco nelle vicinanze e troncalo lì. Solo se non ci sono punti di interruzione migliori nelle vicinanze, dovresti troncare la metà parola.
l'Uomo di latta il

Risposte:


496

È l' operatore ternario e funziona come in C (la parentesi non è richiesta). È un'espressione che funziona come:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

Tuttavia, in Ruby, ifanche un'espressione è così: if a then b else c end=== a ? b : c, ad eccezione dei problemi di precedenza. Entrambe sono espressioni.

Esempi:

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

Si noti che nel primo caso sono necessarie le parentesi (altrimenti Ruby è confuso perché pensa che sia puts if 1con un po 'di spazzatura extra dopo di esso), ma non sono richieste nell'ultimo caso poiché il problema non si presenta.

È possibile utilizzare il modulo "long-if" per la leggibilità su più righe:

question = if question.size > 20 then
  question.slice(0, 20) + "..."
else 
  question
end

Mette 0? 2: 3 dà anche 2 come risultato. Perché?
X_Trust

18
@X_Trust In Ruby, gli unici valori falsi sono nile false. Non molto normale, anzi.
Kroltan,

35
puts true ? "true" : "false"
=> "true"


puts false ? "true" : "false"
=> "false"

Capovolto ma spiega cosa fa.
Tin Man,

4
Piccola modifica puts (true ? "true" : "false")con parentesi. Altrimenti l'ordine delle operazioni non è chiaro. Quando l'ho letto per la prima volta sono rimasto confuso mentre lo leggevo come (puts true) ? "true" : "false"allora mi aspettavo putsdi restituire il valore booleano che poi è diventato il valore della stringa.
Fresheyeball,

26

L'uso di ERB suggerisce che sei su Rails. Se è così, allora considera truncate, un aiuto integrato che farà il lavoro per te:

<% question = truncate(question, :length=>30) %>

Questo è fantastico! cosa voglio esattamente fare !!
Mithun Sreedharan,

11
Sono in ritardo di anni, ma sono rimasto molto colpito da questa risposta, che ha superato tutti gli aspetti sintattici e si è diretto verso ciò che l'interrogante stava cercando di realizzare.
Mike Buckbee,

2
+1, ma erb non implica necessariamente binari (Sinatra, ERB standalone, ecc.).
Fox Wilson,

17

@pst ha dato un'ottima risposta, ma vorrei menzionare che in Ruby l'operatore ternario è scritto su una riga per essere sintatticamente corretto, a differenza di Perl e C dove possiamo scriverlo su più righe:

(true) ? 1 : 0

Normalmente Ruby genererà un errore se si tenta di dividerlo su più righe, ma è possibile utilizzare il \simbolo di continuazione della riga alla fine di una riga e Ruby sarà felice:

(true)   \
  ? 1    \
  : 0

Questo è un semplice esempio, ma può essere molto utile quando si tratta di linee più lunghe poiché mantiene il codice ben strutturato.

È anche possibile usare il ternario senza i caratteri di continuazione della linea mettendo gli operatori per ultimi sulla linea, ma non mi piace o lo consiglio:

(true) ?
  1 :
  0

Penso che questo porti a un codice davvero difficile da leggere poiché il test condizionale e / oi risultati si allungano.

Ho letto i commenti dicendo di non usare l'operatore ternario perché è confuso, ma questa è una cattiva ragione per non usare qualcosa. Con la stessa logica non dovremmo usare espressioni regolari, operatori di intervallo (' ..' e la variazione "flip-flop" apparentemente sconosciuta). Sono potenti se usati correttamente, quindi dovremmo imparare a usarli correttamente.


Perché hai messo le parentesi true?

Considera l'esempio del PO:

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

Il wrapping del test condizionale aiuta a renderlo più leggibile perché separa visivamente il test:

<% question = (question.size > 20) ? question.question.slice(0, 20)+"..." : question.question %>

Ovviamente, l'intero esempio potrebbe essere reso molto più leggibile usando alcune aggiunte giudiziose di spazi bianchi. Questo non è testato ma avrai l'idea:

<% question = (question.size > 20) ? question.question.slice(0, 20) + "..." \
                                   : question.question 
%>

O, più scritto in modo più idiomatico:

<% question = if (question.size > 20)
                question.question.slice(0, 20) + "..."
              else 
                question.question 
              end
%>

Sarebbe facile argomentare che anche la leggibilità soffre molto question.question.


1
Se multilinea, perché non usare solo se ... altrimenti ... fine?
Wayne Conrad,

1
A causa di troppi anni di lavoro in Perl e C? Uso entrambi, a seconda della situazione e se uno è visivamente più chiaro dell'altro. A volte se / else è troppo dettagliato, a volte?: È brutto.
Tin Man il

1
@WayneConrad L'if ha almeno un problema spiegato in questa risposta: stackoverflow.com/a/4252945/2597260 Confronta alcuni modi di utilizzare l'operatore if / ternary
Darek Nędza

Perché hai messo le parentesi true?
Zac,

1
Perché in truerealtà è seduto per quella che sarebbe un'espressione che valuta trueo false. È meglio delimitare visivamente quelli poiché le dichiarazioni ternarie possono rapidamente trasformarsi in rumore visivo, riducendo la leggibilità che influisce sulla manutenibilità.
Tin Man,

3

Un semplice esempio in cui l'operatore controlla se l'id del giocatore è 1 e imposta l'id nemico in base al risultato

player_id=1
....
player_id==1? enemy_id=2 : enemy_id=1
# => enemy=2

E ho trovato un post sull'argomento che mi sembra abbastanza utile.


4
Perché no enemy_id = player_id == 1 ? 2 : 1?
Aaron Blenkush,

1
@AaronBlenkush Grazie per l'input elegante. Sono ancora al livello del noob, probabilmente è per questo :)
Devwanderer,

0

Il codice condition ? statement_A : statement_Bè equivalente a

if condition == true
  statement_A
else
  statement_B
end

0

Il modo più semplice:

param_a = 1
param_b = 2

result = param_a === param_b ? 'Same!' : 'Not same!'

poiché param_anon è uguale a param_ballora il resultvalore di saràNot same!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.