Приведение значений в цикл в Ruby

Это почти наверняка дубликат, но я не могу найти оригинал - я не знаю, какие поисковые термины использовать. Вот почему я нахожусь на Stackoverflow вместо Google :)

Во всяком случае, здесь мой код:

def titleize(say)
 index = 0
 words = say.split
 words.each do |word|
 unless word == "and" || "or" || "over" || "the" || "for"
 word.capitalize!
 end
 if index == 0
 word.capitalize!
 end
 index += 1
 end
 say = words.join(" ")
end

Поскольку индекс объявляется перед циклом, мой if index == 0 не работает. Как я могу сообщить Ruby и использовать индекс объекта? Также: что это называется?

6 ответов

Использование index == 0 отлично, поскольку индекс доступен в вашем цикле. Ваша реальная проблема, вероятно, в этой строке:

word == "and" || "or" || "over" || "the" || "for"

Это всегда true -like! Что вы имеете в виду:

["and", "or", "over", "the", "for"].include? word

Кроме того, существует метод, называемый each_with_index, который вы можете использовать следующим образом:

words.each_with_index do |word, index|


Я думаю, вы хотите использовать with_index. Ваше сравнение слов тоже было разрушено.

def titleize(say)
 words = say.split
 l = ["and", "or", "over", "the", "for"]

 words.each.with_index do |word, index|
 word.capitalize! if index == 0 || !(l.include? word)
 end

 say = words.join(" ")
end

puts(titleize("hello there for you"))
puts(titleize("hi"))
puts(titleize("for"))


Это не то, как работают булевы. Способ оценки:

x == 'a' || 'b'

становится:

(x == 'a') || 'b'

Это эквивалентно:

'b'

То, что вы намереваетесь, переводится на более идиоматический Ruby, есть:

def titleize(say)
 say.split.each_with_index do |word, index|
 if (index == 0)
 word.capitalize!
 else
 case (word)
 when "a", "and", "or", "over", "the", "for"
 # Leave lower-case
 else
 word.capitalize!
 end
 end
 end.join(' ')
end

titleize('the time this is a test for the things!')
# => "The Time This Is a Test for the Things!"


Ваш код возвращает модификацию say, но изменяет содержимое переменной. Похоже, вы хотите изменить аргумент, но я не уверен в этом. Сначала я предложу способ вернуть измененное значение say (но не изменить значение say, а затем покажет, как вы можете изменить код для изменения аргумента.

Обратите внимание, что я не использую индекс и использую оператор case чтобы определить, следует ли заглавные слова после первого.

Код

def titleize(say)
 words = say.split
 return "" if words.empty?
 words.first.capitalize!
 return words.first if words.size == 1
 words[1..-1].each do |word|
 case word
 when "and", "or", "over", "the", "for"
 else
 word.capitalize!
 end
 end
 words.join(' ')
end

Примеры

say = "and now is the time for all Rubyists to hunker down and code"
titleize(say)
 #=> "And Now Is the Time for All Rubyists To Hunker Down and Code"
say
 #=> "and now is the time for all Rubyists to hunker down and code" 

say = " "
titleize(say)
 #=> ""

say = " and "
titleize(say)
 #=> "And"

Изменение аргумента

Если вы хотите изменить аргумент, say, используйте String # replace:

def titleize_and_modify_arg(say)
 words = say.split
 str =
 case words.size
 when 0
 ""
 when 1
 words.first.capitalize
 else
 words.first.capitalize!
 words[1..-1].each do |word|
 case word
 when "and", "or", "over", "the", "for"
 else
 word.capitalize!
 end
 end
 words.join(' ')
 end 
 say.replace(str)
end

say = "and now is the time for all Rubyists to hunker down and code"
titleize_and_modify_arg(say)
 #=> "And Now Is the Time for All Rubyists To Hunker Down and Code"
say
 #=> "And Now Is the Time for All Rubyists To Hunker Down and Code"

say = " and "
titleize_and_modify_arg(say)
 #=> nil
say
 #=> " and "

Обратите внимание на то, что во втором примере, titleize_and_modify_arg модифицирует say правильно, но возвращает nil. Конечно, этот метод можно легко изменить, чтобы вернуть значение, say, и изменить его, если это было необходимо.

Обратите также внимание на то, что в case, когда words.siz => 1, он использует capitalize, а не capitalize! , поскольку последний вернет nil если слово уже заглавное. capitalize! однако это необходимо для случая else.


Я бы сделал это более гибким и более рубиновым

def titleize(sentence,exclusions=[])
 sentence.split.map.with_index do |word,index|
 (index == 0 || !exclusions.include?(word)) ? word.capitalize : word
 end.join(' ')
end

В этом случае я использовал "капитализировать" без взрыва, если любое из слов уже заглавное.

"Hello".capitalize! #=> nil
"Hello".capitalize #=> "Hello"

Он также позволит вам повторно использовать тот же список исключений или изменить их, как вы считаете нужным

Вызовите

exclude = ["and", "or", "over", "the", "for"]
titleize("hello there you are over there", exclude)
#=> "Hello There You Are over There"


Я рекомендую использовать each_index вместо each. См. Здесь.

Попробуй это:

def titleize (say)
 words = say.split
 words.each_index do |index|
 word = words[i]
 unless word == "and" || "or" || "over" || "the" || "for"
 word.capitalize!
 end
 if index == 0
 word.capitalize!
 end
 end
 say = words.join(" ")
end

licensed under cc by-sa 3.0 with attribution.