Як я можу використовувати умовний оператор (? :) у Ruby?


303

Як умовний оператор ( ? :) використовується в Ruby?

Наприклад, чи правильно це?

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

1
так, я думаю, але я також думаю, що ти можеш досягти цього: question=question[0,20] Якщо він був меншим за 20, це не змінить.
DGM

мені також потрібно додати "...", якщо довжина більша за 20
Mithun Sreedharan

1
Будьте обережні, сліпо відбиваючи рядок у заданому стовпці. Ви можете вирізати слово посередині, додавши еліпсис ('...'), що виглядає погано. Натомість шукайте знаки пунктуації чи знаку пробілу поблизу та вкорочуйте там. Тільки якщо поблизу немає кращої точки розриву, слід урізати середину слова.
Олов'яний чоловік

Відповіді:


496

Це потрійний оператор , і він працює як у C (дужки не потрібні). Це вираз, який працює так:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

Однак у Ruby ifтакож є вираз так: if a then b else c end=== a ? b : c, за винятком пріоритетних питань. Обидва - це вирази.

Приклади:

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

Зверніть увагу, що в першому випадку потрібні круглі дужки (інакше Рубі плутається через те, що думає, що це puts if 1з деякими зайвими мотлохами після нього), але вони не потрібні в останньому випадку, оскільки зазначене питання не виникає.

Ви можете використовувати форму "long-if" для читабельності в декількох рядках:

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

Ставить 0? 2: 3 також дає 2. Чому так?
X_Trust

18
@X_Trust У Ruby єдиними фальшивими значеннями є nilі false. Справді, не дуже звично.
Кролтан

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


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

Терсе, але пояснює, що це робить.
Олов'яний чоловік

4
Невелике редагування puts (true ? "true" : "false")з дужками. Інакше порядок операцій незрозумілий. Коли я вперше прочитав це, я був розгублений, коли читав, як (puts true) ? "true" : "false"тоді очікував putsповернути булеве значення, яке потім стало значенням рядка.
Fresheyeball

26

Ваше використання ERB говорить про те, що ви перебуваєте в Rails. Якщо так, то подумайте truncate, що вбудований помічник, який зробить роботу за вас:

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

Це чудово! що я точно хочу зробити !!
Мітхун Средхаран

11
На це пізно, але я був дуже вражений цією відповіддю, коли він проскочив усі синтаксичні аспекти і пішов правильно до того, що запитуючий намагався досягти.
Майк Бакбі

2
+1, але erb не обов'язково означає рейки (Сінатра, автономна ERB тощо).
Фокс Вілсон

17

@pst дав чудову відповідь, але я хотів би зазначити, що в Ruby потрійний оператор записаний на одному рядку, щоб бути синтаксично правильним, на відміну від Perl і C, де ми можемо записати його в декількох рядках:

(true) ? 1 : 0

Зазвичай Ruby призведе до помилки, якщо ви спробуєте розділити її на кілька рядків, але ви можете використовувати \символ продовження рядка в кінці рядка, і Ruby буде задоволений:

(true)   \
  ? 1    \
  : 0

Це простий приклад, але він може бути дуже корисним при роботі з довшими рядками, оскільки він зберігає код добре викладеним.

Також можна використовувати термінал без символів продовження рядків, поставивши операторів останніми в рядку, але це мені не подобається чи не рекомендую:

(true) ?
  1 :
  0

Я думаю, що це призводить до дійсно важкого для читання коду, оскільки умовний тест та / або результати стають довшими.

Я читав коментарі, в яких говорилося, що не використовувати термінального оператора, оскільки це заплутано, але це погана причина, щоб щось не використовувати. За цією ж логікою ми не повинні використовувати регулярні вирази, оператори діапазону (' ..' і, здавалося б, невідомі варіації "відкидання"). Вони потужні при правильному використанні, тому ми повинні навчитися правильно їх використовувати.


Чому ти поставив дужки навколо true?

Розглянемо приклад ОП:

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

Обгортання умовного тесту допомагає зробити його більш читабельним, оскільки він візуально розділяє тест:

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

Звичайно, весь приклад можна зробити набагато більш читабельним, використовуючи деякі розумні доповнення пробілів. Це не перевірено, але ви отримаєте ідею:

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

Або, написані більш ідіоматично:

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

Неважко аргументувати, що читабельність question.questionтеж погано страждає .


1
Якщо багаторядковий, чому б не просто використовувати, якщо ... ще ... закінчитися?
Уейн Конрад

1
Через занадто багато років роботи в Perl та C? Я використовую будь-яке, залежно від ситуації та того, чи є один візуально чіткіший за інший. Іноді якщо / else занадто багатослівний, іноді ?: некрасивий.
Людина з жерсті

1
@WayneConrad Якщо у цій відповіді є пояснення хоча б однієї проблеми: stackoverflow.com/a/4252945/2597260 Порівняйте кілька способів використання багатолінійного оператора if / ternary
Darek Nędza

Чому ти поставив дужки навколо true?
Зак

1
Тому що trueнасправді сидить за тим, що було б виразом, який оцінює до trueабо false. Краще візуально розмежувати їх, оскільки потрійні висловлювання можуть швидко перерости у візуальний шум, зменшуючи читабельність, що впливає на ремонтопридатність.
Олов'яний чоловік

3

Простий приклад, коли оператор перевіряє, чи є ідентифікатор гравця 1, і встановлює ідентифікатор ворога залежно від результату

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

І я знайшов повідомлення про цю тему, яка здається досить корисною.


4
Чому ні enemy_id = player_id == 1 ? 2 : 1?
Аарон Бленкуш

1
@AaronBlenkush Дякую за елегантний вклад. Я досі в рівні noob, напевно, саме тому :)
devwanderer


0

Найпростіший спосіб:

param_a = 1
param_b = 2

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

так як param_aне дорівнює , param_bто resultзначення «s будеNot same!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.