Bagaimana cara menggunakan operator kondisional (? :) di Ruby?

303

Bagaimana operator kondisional ( ? :) digunakan di Ruby?

Misalnya, apakah ini benar?

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Mithun Sreedharan
sumber
1
ya, saya pikir, tetapi saya juga berpikir Anda bisa mencapainya dengan: question=question[0,20] Jika lebih kecil dari 20, itu tidak akan mengubahnya apa pun.
DGM
saya juga perlu menambahkan '...' jika panjangnya lebih besar dari 20
Mithun Sreedharan
1
Hati-hati memotong garis pada kolom yang diberikan. Anda dapat memotong kata di tengah jalan lalu menambahkan elipsis ('...'), yang terlihat buruk. Sebagai gantinya, cari tanda baca terdekat atau karakter spasi, dan potong di sana. Hanya jika tidak ada titik puncak yang lebih baik di dekatnya Anda harus memotong tengah kata.
the Tin Man

Jawaban:

496

Ini adalah operator ternary , dan berfungsi seperti di C (tanda kurung tidak diperlukan). Itu ekspresi yang bekerja seperti:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

Namun, di Ruby, ifada juga ekspresi: if a then b else c end=== a ? b : c, kecuali untuk masalah prioritas. Keduanya adalah ekspresi.

Contoh:

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

Perhatikan bahwa dalam kurung kasus pertama diperlukan (jika tidak, Ruby bingung karena menganggapnya puts if 1dengan beberapa sampah tambahan setelah itu), tetapi mereka tidak diperlukan dalam kasus terakhir karena masalah tersebut tidak muncul.

Anda dapat menggunakan formulir "long-if" untuk keterbacaan pada beberapa baris:

question = if question.size > 20 then
  question.slice(0, 20) + "..."
else 
  question
end
Manusia Timah
sumber
Menempatkan 0? 2: 3 juga memberi 2 sebagai hasilnya. Mengapa demikian?
X_Trust
18
@X_Trust Di Ruby, satu-satunya nilai palsu adalah nildan false. Memang tidak terlalu biasa.
Kroltan
35
puts true ? "true" : "false"
=> "true"


puts false ? "true" : "false"
=> "false"
DGM
sumber
Terse tetapi menjelaskan apa fungsinya.
the Tin Man
4
Edit kecil puts (true ? "true" : "false")dengan tanda kurung. Kalau tidak, urutan operasi tidak jelas. Ketika saya pertama kali membaca ini saya bingung karena saya membacanya karena (puts true) ? "true" : "false"kemudian diharapkan putsuntuk mengembalikan boolean yang kemudian menjadi nilai string.
Fresheyeball
26

Penggunaan ERB Anda menunjukkan bahwa Anda berada di Rails. Jika demikian, pertimbangkanlah truncate, penolong bawaan yang akan melakukan pekerjaan untuk Anda:

<% question = truncate(question, :length=>30) %>
Wayne Conrad
sumber
Ini bagus! apa yang sebenarnya ingin saya lakukan !!
Mithun Sreedharan
11
Ini terlambat beberapa tahun, tetapi saya sangat terkesan dengan jawaban ini karena melompati semua aspek sintaksis dan langsung menuju apa yang ingin dicapai oleh si penanya.
Mike Buckbee
2
+1, tetapi erb tidak selalu menyiratkan rel (Sinatra, ERB mandiri, dll).
Fox Wilson
17

@pst memberikan jawaban yang bagus, tetapi saya ingin menyebutkan bahwa di Ruby operator ternary ditulis pada satu baris agar benar secara sintaksis, tidak seperti Perl dan C di mana kita dapat menulisnya di beberapa baris:

(true) ? 1 : 0

Biasanya Ruby akan memunculkan kesalahan jika Anda mencoba membaginya ke beberapa baris, tetapi Anda dapat menggunakan \simbol kelanjutan garis di akhir baris dan Ruby akan senang:

(true)   \
  ? 1    \
  : 0

Ini adalah contoh sederhana, tetapi bisa sangat berguna ketika berhadapan dengan garis yang lebih panjang karena membuat kode ditata dengan baik.

Dimungkinkan juga untuk menggunakan ternary tanpa karakter kelanjutan garis dengan menempatkan operator sebagai yang terakhir, tetapi saya tidak suka atau merekomendasikannya:

(true) ?
  1 :
  0

Saya pikir itu mengarah ke sangat sulit untuk membaca kode karena tes bersyarat dan / atau hasil menjadi lebih lama.

Saya sudah membaca komentar yang mengatakan tidak menggunakan operator ternary karena membingungkan, tetapi itu adalah alasan buruk untuk tidak menggunakan sesuatu. Dengan logika yang sama kita tidak boleh menggunakan ekspresi reguler, operator jangkauan (' ..' dan variasi "flip-flop" yang tampaknya tidak dikenal). Mereka kuat ketika digunakan dengan benar, jadi kita harus belajar menggunakannya dengan benar.


Mengapa Anda menaruh tanda kurung true?

Pertimbangkan contoh OP:

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

Membungkus tes bersyarat membantu membuatnya lebih mudah dibaca karena memisahkan tes secara visual:

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

Tentu saja, seluruh contoh bisa dibuat lebih mudah dibaca dengan menggunakan beberapa tambahan spasi kosong. Ini belum diuji tetapi Anda akan mendapatkan ide:

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

Atau, lebih banyak menulis lebih idiomatis:

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

Akan mudah untuk berargumen bahwa keterbacaan juga sangat buruk question.question.

Manusia Timah
sumber
1
Jika multi-line, mengapa tidak hanya menggunakan jika ... yang lain ... berakhir?
Wayne Conrad
1
Karena sudah bertahun-tahun bekerja di Perl dan C? Saya menggunakan keduanya, tergantung pada situasinya dan apakah yang satu secara visual lebih jelas daripada yang lain. Terkadang jika / yang lain terlalu bertele-tele, terkadang?: Jelek.
the Tin Man
1
@WayneConrad If memiliki setidaknya satu masalah yang dijelaskan dalam jawaban ini: stackoverflow.com/a/4252945/2597260 Bandingkan beberapa cara menggunakan operator multiline if / ternary: gist.github.com/nedzadarek/0f9f99755d42bad10c30
Darek Nędza
Mengapa Anda menaruh tanda kurung true?
Zac
1
Karena truesebenarnya duduk untuk apa yang akan menjadi ekspresi yang mengevaluasi trueatau false. Lebih baik untuk membatasi secara visual karena pernyataan ternary dapat dengan cepat berubah menjadi noise visual, mengurangi keterbacaan yang memengaruhi pemeliharaan.
the Tin Man
3

Contoh sederhana di mana operator memeriksa apakah id pemain adalah 1 dan menetapkan id musuh tergantung pada hasilnya

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

Dan saya menemukan posting tentang topik yang tampaknya cukup membantu.

devwanderer
sumber
4
Mengapa tidak enemy_id = player_id == 1 ? 2 : 1?
Aaron Blenkush
1
@AaronBlenkush Terima kasih atas input yang elegan. Saya masih di level noob, mungkin itu sebabnya :)
devwanderer
0

Kode condition ? statement_A : statement_Bini setara dengan

if condition == true
  statement_A
else
  statement_B
end
Umesh Malhotra
sumber
0

Cara termudah:

param_a = 1
param_b = 2

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

karena param_atidak sama dengan param_bmaka resultnilai akan menjadiNot same!

Adrian Eranzi
sumber