Reputation: 29
class Book
# write your code here
attr_accessor :title
def title= (title)
@title = title.split()
@title = @title.map {
|x|
index = @title.index(x)
if x == 'and' or x == 'in' or x == 'of' or x == 'the' or x == 'a' or x == 'an' and index != 0
x = x
else
x.capitalize
end
}
@title = @title.join(" ")
return @title
end
end
This is an exercise from the Project Ruby on the Odin Project. It's about capitalizing the titles of a book bound to some certain conditions life if the word is a preposition or an article or a conjunction then dont capitalize it unless it occurs in the beginning of the title then capitalize it. I have written the code for it but it isn't working as you can see :
index = @title.index(x)
if x == 'and' or x == 'in' or x == 'of' or x == 'the' or x == 'a' or x == 'an' and index != 0
x = x
else
x.capitalize
end
But again it doesn't work
expected: "The Man in the Iron Mask"
got: "The Man in The Iron Mask"
The second The
gets capitalized too when I have said in the if
statement that if it isn't equal to the first word then don't capitalize it but it still capitalizes it.
Upvotes: 0
Views: 66
Reputation: 110675
The problem with your code has been identified. One way to obtain the desired result is to use String#gsub with a simple regular expression.
LITTLE_WORDS = %w| a an and in of the |
#=> ["a", "an", "and", "in", "of", "the"]
LWR = /\b#{LITTLE_WORDS.join('|')}\b/i
#=> /\ba|an|and|in|of|the\b/i
def normalize(str)
str.gsub(/\S+/) do |word|
if Regexp.last_match.begin(0).zero?
word.capitalize
else
word.match?(LWR) ? word.downcase : word.capitalize
end
end
end
normalize("tHe cat and A hAt")
#=> "The Cat and a Hat"
See Regexp::last_match (same as the value of the global variable $~
) and MatchData#begin. Notice that this preserves spacing in the string.
In the publishing industry such articles, prepositions and conjunctions are often referred to as "little words", and written "a", "an", "and", "in", "of", "the".
Upvotes: 0
Reputation: 106882
Because index(x)
always returns the first match.
I would rewrite it like this:
class Book
attr_accessor :title
DO_NOT_CAPITALIZE = %w[and in of the a an]
def title=(title)
words = title.split.map do |word|
# capitalize all word that are not excluded
DO_NOT_CAPITALIZE.include?(word) ? word : word.capitalize
end
# always capitalize the first word
@title = words.join(' ').capitalize
end
end
Upvotes: 4