Reputation: 115
This is almost certainly a duplicate, but I can't find the original - I don't know the search terms to use. Which is why I'm on Stackoverflow instead of Google :)
Anyhow, here's my code:
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
Because index is declared before the loop, my if index == 0
is not working.
How do I let Ruby know about and use my object index? Also: what is this called?
Upvotes: 1
Views: 97
Reputation: 110755
Your code returns the modification of say
, but does change the contents of the variable. It appears that you want to modify the argument, but I'm not sure about that. I will first suggest a way to return the modified value of say
(but not alter the value of say
, and then will show how you could change the code to modify the argument.
Notice that I do not employ an index, and use a case
statement to determine whether words after the first should be capitalized.
Code
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
Examples
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"
Modifying the Argument
If you wish to modify the argument say
, use 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 "
Notice that in the second example, titleize_and_modify_arg
modifies say
correctly, but returns nil
. Of course, the method could be easily changed to return the value of say
, as well as changing it, if that were desired.
Note also that, in the case
statement, when words.siz => 1
, it's capitalize
, not capitalize!
, as the latter would return nil
if the word is already capitalized. capitalize!
is need for the else
case, however.
Upvotes: 0
Reputation: 29613
I would do this it is more flexible and more ruby-esque
def titleize(sentence,exclusions=[])
sentence.split.map.with_index do |word,index|
(index == 0 || !exclusions.include?(word)) ? word.capitalize : word
end.join(' ')
end
For this case i used 'capitalize' without the bang in case any of the words are already capitalized.
"Hello".capitalize! #=> nil
"Hello".capitalize #=> "Hello"
It will also let you re-use the same list of exclusion or change them as you see fit
Call as
exclude = ["and", "or", "over", "the", "for"]
titleize("hello there you are over there", exclude)
#=> "Hello There You Are over There"
Upvotes: 0
Reputation: 211750
That's not how booleans work. The way this is evaluated is:
x == 'a' || 'b'
Becomes:
(x == 'a') || 'b'
Which is equivalent to:
'b'
What you're intending, translated to more idiomatic Ruby, is:
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!"
Upvotes: 1
Reputation: 19
I recommend using each_index
instead of each
. See here.
Try this:
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
Upvotes: -3
Reputation: 31761
I think you want to use with_index
. Your word comparison was busted too.
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"))
Upvotes: 2
Reputation: 44725
Using index == 0
is perfectly fine as index is accessible within your loop. Your real problem is probably in this line:
word == "and" || "or" || "over" || "the" || "for"
This is always true
-like! What you mean is:
["and", "or", "over", "the", "for"].include? word
Apart form that there is a method called each_with_index
, which you can use like this:
words.each_with_index do |word, index|
Upvotes: 8