Следующий код должен напечатать один из трех вариантов, заданных в зависимости от результатов любой из проверок ==
, но это не так. Это дает nil
для любого значения your_message, предоставленного через gets.chomp
. Может кто-нибудь, пожалуйста, скажите мне, что не так с моим кодом?
def stupid_coach(your_message)
case your_message
when your_message == your_message.include?("?")
p "Silly question, get dressed and go to work!"
when !your_message == your_message.include?("?")
p "I don't care, get dressed and go to work!"
when your_message == "I am going to work now!"
exit
end
end
Привет pjs ... спасибо за ваш отзыв. Помимо чтения документации, я хотел бы пообщаться со своими старшими/коллегами, чтобы понять ошибку или ошибку... Я знаю, как включать и обрабатывать кейсы, чего я не знаю, так это почему в моем текущем контексте код не работает. работает по назначению. Есть идеи?. Спасибо.
«Я умею включать и работать с кейсами». Извините, но это явно не так. Отсюда мое предложение просмотреть документацию.
Большой совет: если вы знаете, что .include?
возвращает либо true
, либо false
, запустите свой выбор irb
или pry
и посмотрите, что произойдет, когда вы введете "some string" == true
или "some string" == false
. Тогда попробуйте это, используя ===
. Вы должны понять, почему ваше утверждение case
никогда не дает совпадений.
Явные возвраты в вашем редактировании не нужны. Отдельно стоит отметить, что считается плохим этикетом SO коренным образом изменить ваш вопрос таким образом, чтобы сделать недействительными существующие ответы. Обычно правильнее всего открыть связанный вопрос, который ссылается на оригинал, если у вас есть отдельные дополнительные вопросы.
Если этот комментарий недостаточно проясняет ваши последующие изменения - я думаю, что да, но ваш пробег может отличаться - тогда, пожалуйста, откройте новый вопрос о том, как выполнить дополнительное сравнение, которое вы хотите, в выражении случая, и, возможно, получить лучшее объяснение, чем может уместиться в комментариях, о том, почему это сравнение не делает того, что вы ожидаете.
Привет, Тодд, большое спасибо за ваш ценный комментарий... Мне удалось заставить его работать. Ваше утверждение абсолютно верно... проблема заключалась в порядке моих проверок... это было ключевым моментом. И, конечно же, тот факт, что ранее я сравнивал строку с логическим значением... большое спасибо за вашу решительную и терпеливую поддержку.
В выражении case
when
сравнивает значение со значением.
В вашем случае вы сравниваете your_message
, который предположительно является строкой, с логическими значениями.
Рассмотрим очень простой пример:
irb(main):001:1* case "hello"
irb(main):002:1* when true
irb(main):003:1* puts "foo"
irb(main):004:1* else
irb(main):005:1* puts "bar"
irb(main):006:0> end
bar
=> nil
Вы можете использовать регулярные выражения или сопоставлять строки.
def stupid_coach(your_message)
case your_message
when "I am going to work now!"
exit
when /\?/
p "Silly question, get dressed and go to work!"
else
p "I don't care, get dressed and go to work!"
end
end
Хотя я не уверен, что вы на самом деле хотите выйти из программы так, как это сделает ваш код, если он нажмет exit
, а сам метод вернет nil
.
Если вы хотите, чтобы он возвращал строки, а не печатал их:
def stupid_coach(your_message)
case your_message
when "I am going to work now!"
exit
when /\?/
"Silly question, get dressed and go to work!"
else
"I don't care, get dressed and go to work!"
end
end
Спасибо, ребята... Я усовершенствовал свой код следующим образом, но при использовании следующих тестовых строк TEST! и тест не дает правильных результатов в соответствии с моим кодом...
Падежное выражение работает не так, как вы думаете. Это не просто еще один способ выразить условия if/then. Под капотом case реализует оператор ===
для выражения при передаче аргумента case или позволяет вам использовать его как набор операторов if, если вы не передаете начальный аргумент. Он также выполняет сопоставление с образцом, но это выходит за рамки этого вопроса.
Когда вы предоставляете аргумент case, такой как case your_message
, тогда каждый оператор when будет оцениваться как выражение против аргумента с использованием тройки, специфичной для класса, а не условного выражения, которое, как вы думаете, вы ему даете. Это легко исправить, передав аргумент в case. Например:
your_message = "foo?"
case
when your_message.end_with?("?")
"bar"
end
#=> "bar"
Теперь, вместо того, чтобы эффективно произносить "foo?" === true
(что, очевидно, вернет false
), Ruby просто оценивает, является ли когда-утверждение правдивым или нет. Основываясь на вашем существующем коде, это, вероятно, самый простой способ получить ожидаемое поведение.
В качестве альтернативы вы можете реструктурировать свой оператор case, чтобы использовать процедуры, лямбда-выражения или даже регулярные выражения, которые могут соответствовать тройному сравнению, поскольку оно реализовано классом. Например, рассмотрим следующий пример, в котором используется Proc#=== для сравнения результатов лямбда.
your_message = "foo? \n"
case your_message
when ->{ _1.strip.end_with? "?" }
"baz"
end
#=> "baz"
Это в основном передает аргумент case (например, your_message) в лямбду, где вы затем можете вызывать методы для аргумента, чтобы оценить его истинность. Это более сложный подход, но он может быть полезен.
Поскольку регулярные выражения также поддерживают метод threequals, вы можете использовать и его:
your_message = "foo?"
case your_message
when /\?$/
"quux"
end
#=> "quux"
Вы также должны учитывать такие вещи, как зависимость от порядка. В вашем примере кода, даже если бы не было других проблем, "I am going to work now!"
никогда не будет сопоставляться, потому что предыдущие операторы when (если они работают) будут возвращать значение, основанное на наличии или отсутствии знака вопроса, прежде чем вы когда-либо достигли этого конкретного сравнения . Выражения case не «проваливаются», как в других языках, поэтому вам необходимо учитывать приоритет операторов так же, как и в управляющем выражении if/elsif/else/end.
Следующее намного проще и отлично работает. Он возвращает действительные результаты и не возвращает ноль. Предполагается, что your_message может #respond_to?(:strip), но вы можете изменить код, если хотите.
def stupid_coach your_message
case your_message.strip
when "I am going to work now!"
"This works when checked before matching for '?'."
when /\?$/
"Silly question, get dressed and go to work!"
else
"I don't care, get dressed and go to work!"
end
end
Вы можете протестировать его на массиве выборочных входных данных. Результаты кажутся мне достоверными, но вы, безусловно, можете применить их к другим значениям String, если считаете, что есть крайний случай.
["Foo?", "Bar.", "I am going to work now!"]
.map { stupid_coach _1 }
#=>
["Silly question, get dressed and go to work!",
"I don't care, get dressed and go to work!",
"This can match if checked before mactching for '?'."]
Порядок, в котором вы выполняете образцы, не имеет значения. Если вы измените порядок тестового массива, вы все равно получите правильные результаты. Пока порядок ваших операторов when правильный и вы используете правильный тип выражения для сравнений, вы можете заставить выражение case делать то, что хотите, но не обязательно так, как вы изначально ожидали.
Привет, Тодд... твои комментарии ОЧЕНЬ полезны, большое спасибо. Я переупорядочил свои случаи КОГДА... однако мой "когда your_message.upcase && your_message.include?("!")" не работает должным образом... в основном, он возвращает выражение, когда тестовая строка " тест!" что неверно... оно должно возвращать выражение ТОЛЬКО при выполнении ОБА условий... это "ТЕСТ!". Любые мысли? Большое спасибо,
@ Panamaniac507 Вам нужно будет открыть отдельный вопрос об этом, если вы хотите получить подробный ответ. Короткая версия заключается в том, что ваше первое выражение не возвращает логическое значение. Вы, вероятно, хотите when your_message.eql?(your_message.upcase) && your_message.end_with?("!")
, но трудно сказать, не видя полного контекста. Почти все в Ruby является выражением, поэтому важно понимать истинность, приоритет и сравнение выражений. Возможно, вы захотите придерживаться для этого операторов if, поскольку они больше соответствуют тому, как вы думаете о своем коде.
Итак, вы хотите проверить, равно ли содержимое
your_message
значениюtrue
илиfalse
? Я думаю, вам нужно вернуться и перечитать документацию по .include? и на случае.