I think I'm close, but the regex isn't evaluating. Hoping someone may know why.
def new_title(title)
words = title.split(' ')
words = [words[0].capitalize] + words[1..-1].map do |w|
if w =~ /and|an|a|the|in|if|of/
w
else
w.capitalize
end
end
words.join(' ')
end
When I pass in lowercase titles, they get returned as lowercase.
You need to properly anchor your regular expression:
new_title("the last hope")
# => "The last Hope"
This is because /a/ matches a word with an a in it. /\Aa\Z/ matches a string that consists entirely of a, and /\A(a|of|...)\Z/ matches against a set of words.
In any case, what you might want is this:
case (w)
when 'and', 'an', 'a', 'the', 'in', 'if', 'of'
w
else
w.capitalize
end
Using a regular expression here is a bit heavy handed. What you want is an exclusion list.
This is called titleize, and is implemented like this:
def titleize(word)
humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
end
Se the doc.
If you want fancy titlezing, check out granth's titleize
Your regular expression should be checking the whole word (^word$). Anyway, isn't more simple to use Enumerable#include?:
def new_title(title)
words = title.split(' ')
rest_words = words.drop(1).map do |word|
%w(and an a the in if of).include?(word) ? word : word.capitalize
end
([words[0].capitalize] + rest_words).join(" ")
end
Related
Hi I'm building a function that has me take any instance of "u" or "you" in a string and replace it with a specific word. I can go in and isolate the instances no problem but I cannot get the words to output properly. So far I have.
def autocorrect(input)
#replace = [['you','u'], ['your sister']]
#replace.each{|replaced| input.gsub!(replaced[0], replaced[1])}
input.split(" ")
if (input == "u" && input.length == 1) || input == "you"
input.replace("your sister")
end
input.join(" ")
end
The ideal output would be:
autocorrect("I am so smitten with you")
"I am smitten with your sister"
I don't know how to get the last part correct, I can't think of a good method to use. Any help would be greatly appreciated.
The problem you're having with your code is that you call input.split(" ") but you don't save that to anything, and then you check for input == "u" # ..., and input is still the entire string, so if you called autocorrect('u') or autocorrect('you') you would get "your sister" back, except for the next line: input.join(" ") will throw an error.
This error is because, remember input is still the original string, not an array of each word, and strings don't have a join method.
To get your code working with the fewest changes possible, you can change it to:
def autocorrect(input)
#replace = [['you','u'], ['your sister']]
#replace.each{|replaced| input.gsub!(replaced[0], replaced[1])}
input.split(" ").map do |word|
if (word == "u" && word.length == 1) || word == "you"
"your sister"
else
word
end
end.join(" ")
end
So, now, you are doing something with each word after you split(" ") the input, and you are checking each word against "u" and "you", instead of the entire input string. You then map either the replacement word, or the original, and then join them back into a single string to return them.
As an alternative, shorter way, you can use String#gsub which can take a Hash as the second parameter to do substitutions:
If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.
def autocorrect(input)
replace = { 'you' => 'your sister',
'u' => 'your sister',
'another word' => 'something else entirely' }
input.gsub(/\b(#{replace.keys.join('|')})\b/, replace)
end
autocorrect("I am u so smitten with utopia you and another word")
# => "I am your sister so smitten with utopia your sister and something else entirely"
the regex in that example comes out looking like:
/\b(you|u|another word)\b/
with \b being any word boundary.
Simple array mapping would do the job:
"I am u so smuitten with utopia you".split(' ').map{|word| %w(you u).include?(word) ? 'your sister' : word}.join(' ')
#=> "I am your sister so smuitten with utopia your sister"
Your method would be:
def autocorrect(input)
input.split(' ').map{|word| %w(you u).include?(word) ? 'your sister' : word}.join(' ')
end
autocorrect("I am so smitten with you")
#=> "I am smitten with your sister"
I want to replace a character in string when a particular condition is satisfied. So , I went through the API doc of Ruby and found the gsub , gsub! etc for similar purpose. When I implemented that in my program I didn't got any error but din't got the desired output too.
The code which I was trying is this :
name.each_char { |c|
if name[c] == "a"
name.sub( name[c] , c )
puts "matched.... "
end
So , for example , I have a string called huzefa and want to replace all the letters with its index numbers . So , what is the way to do it ? Please explain in detail by giving a simple example.
You could pass block to gsub and do whatever you want when match happend.
To do it inplace you could use gsub! method.
name = "Amanda"
new_name = name.gsub("a") do |letter|
puts "I've met letter: " + letter
"*"
end
# I've met letter: a
# I've met letter: a
# => "Am*nd*"
If you want to work with indexes, you could do something like this:
new_name = name.chars.map.with_index do |c, i|
if i.odd?
"*"
else
c
end
end.join
#=> => "A*a*d*"
Here c and i are passed to the block. c is a character and i is an index.
if name=huzefa and you want to replace 'a' with its index..
name.split(//).map.with_index{|x,y| (x=='a')? y : x}.join
to result in #> "huzef5"
I answered my own question. Forgot to initialize count = 0
I have a bunch of sentences in a paragraph.
a = "Hello there. this is the best class. but does not offer anything." as an example.
To figure out if the first letter is capitalized, my thought is to .split the string so that a_sentence = a.split(".")
I know I can "hello world".capitalize! so that if it was nil it means to me that it was already capitalized
EDIT
Now I can use array method to go through value and use '.capitalize!
And I know I can check if something is .strip.capitalize!.nil?
But I can't seem to output how many were capitalized.
EDIT
a_sentence.each do |sentence|
if (sentence.strip.capitalize!.nil?)
count += 1
puts "#{count} capitalized"
end
end
It outputs:
1 capitalized
Thanks for all your help. I'll stick with the above code I can understand within the framework I only know in Ruby. :)
Try this:
b = []
a.split(".").each do |sentence|
b << sentence.strip.capitalize
end
b = b.join(". ") + "."
# => "Hello there. This is the best class. But does not offer anything."
Your post's title is misleading because from your code, it seems that you want to get the count of capitalized letters at the beginning of a sentence.
Assuming that every sentence is finishing on a period (a full stop) followed by a space, the following should work for you:
split_str = ". "
regex = /^[A-Z]/
paragraph_text.split(split_str).count do |sentence|
regex.match(sentence)
end
And if you want to simply ensure that each starting letter is capitalized, you could try the following:
paragraph_text.split(split_str).map(&:capitalize).join(split_str) + split_str
There's no need to split the string into sentences:
str = "It was the best of times. sound familiar? Out, damn spot! oh, my."
str.scan(/(?:^|[.!?]\s)\s*\K[A-Z]/).length
#=> 2
The regex could be written with documentation by adding x after the closing /:
r = /
(?: # start a non-capture group
^|[.!?]\s # match ^ or (|) any of ([]) ., ! or ?, then one whitespace char
) # end non-capture group
\s* # match any number of whitespace chars
\K # forget the preceding match
[A-Z] # match one capital letter
/x
a = str.scan(r)
#=> ["I", "O"]
a.length
#=> 2
Instead of Array#length, you could use its alias, size, or Array#count.
You can count how many were capitalized, like this:
a = "Hello there. this is the best class. but does not offer anything."
a_sentence = a.split(".")
a_sentence.inject(0) { |sum, s| s.strip!; s.capitalize!.nil? ? sum += 1 : sum }
# => 1
a_sentence
# => ["Hello there", "This is the best class", "But does not offer anything"]
And then put it back together, like this:
"#{a_sentence.join('. ')}."
# => "Hello there. This is the best class. But does not offer anything."
EDIT
As #Humza sugested, you could use count:
a_sentence.count { |s| s.strip!; s.capitalize!.nil? }
# => 1
I have a long string, "the silver rider on his back and the palm tree". I would like to write a Ruby method that capitalizes all words except "on", "the", and "and" in the middle of the sentence, but have the "the" capitalized at the beginning?
Here is what I have so far:
def title(word)
small_words = %w[on the and]
word.split(' ').map do |w|
unless small_words.include?(w)
w.capitalize
else
w
end
end.join(' ')
end
This code actually does most of what I need but don't know how to include or exclude for that matter the "the" at the beginning of the sentence.
This will capitalize all the words, except for the stop words (your small words) that aren't the first in the sentence.
def title(sentence)
stop_words = %w{a an and the or for of nor} #there is no such thing as a definite list of stop words, so you may edit it according to your needs.
sentence.split.each_with_index.map{|word, index| stop_words.include?(word) && index > 0 ? word : word.capitalize }.join(" ")
end
It’s easiest to just forget about the special case of the first letter initially and then handle it after doing everything else:
def title(sentence)
small_words = %w[on the and]
capitalized_words = sentence.split(' ').map do |word|
small_words.include?(word) ? word : word.capitalize
end
capitalized_words.first.capitalize!
capitalized_words.join(' ')
end
This also capitalizes any “small word” at the beginning, not just “the”—but I think that’s probably what you want anyway.
A simple mod to your existing code would make it work:
def title( word )
small_words = %w[on the and]
word.split(' ').map.with_index do |w, i|
unless (small_words.include? w) and (i > 0)
w.capitalize
else
w
end
end.join(' ')
end
SmallWords = %w[on the and]
def title word
word.gsub(/[\w']+/){
SmallWords.include?($&) && $~.begin(0).zero?.! ? $& : $&.capitalize
}
end
Sorry, yet another question regarding the TestFirst.org Ruby exercise to write a 'Pig Latin' method, coming from a newbie. The other answers helped somewhat but I wasn't able to adapt them successfully. The main issue is that I'm trying to write a method to scan through a string of words (not just a single word), modify some of the words (if applicable), then return the full string back.
Below is my code attempting to perform the first part of the exercise, which is to append "ay" to any word beginning with a vowel. However, it is not working for me -- seems the .include? never returns true from comparing with a single letter(?)
Any help is much appreciated!
# PIG LATIN
# If any word within the input string begins with a vowel, add an "ay" to the end of the word
def translate(string)
vowels_array = %w{a e i o u y}
consonants_array = ('a'..'z').to_a - vowels_array
string_array = string.split
string_array.each do |word|
if vowels_array.include?(word[0])
word + 'ay'
end
end
return string_array.join(" ")
end
translate("apple orange mango") # => "appleay orangeay mango" but does not
string_array.each just iterates through string_array, doesn't change it; in order to update the contents of an array you should use map!:
# ...
string_array.map! do |word|
if vowels_array.include?(word[0])
word + 'ay'
else
word
end
end
# ...
translate("apple orange mango") #=> "appleay orangeay mango"
The purpose of else word end is to return the word also when the if condition is not satisfied.
Out of the array manipulating point of view, in most cases the best way to manipulate strings are regexps:
def translate(string)
string.gsub(/(^|\s)[aeiouy]\S*/i, '\0ay')
end
translate("apple orange mango") #=> "appleay orangeay mango"
Hash key lookup may be a bit faster
v= Hash['a', 1, 'o', '1', 'i', 1, 'u', 1, 'e', 1]
ws= %w(apple orange mango)
ws.map! do |w|
v[w[0]].nil? ? w : "#{w}ay"
end
p ws
Sounds like a job for a regular expression:
str = 'apple orange mango'
str.gsub(/\b[aeiou]\w*\b/, '\0ay')
#=> "appleay orangeay mango"
gsub will look for all occurences of a pattern (the first argument) and replace it with a string (the second argument). Inside that string, you can refer back to the matched pattern with \0 and append ay to it, which leaves us with \0ay.
Now the pattern (the actual regular expression) means “Capture whole words (\b matches word boundaries), that start with one of [aeiou] and end with zero ore more word characters (\w*)”.
So your complete method can be boiled down to:
def translate(string)
string.gsub /\b[aeiou]\w*\b/, '\0ay'
end
Et voilá!
Try:
def translate(string)
new_string = ''
string.split.each do |word|
if 'aoiue'.include?(word[0])
new_string += word + 'ay '
else
new_string += word + ' '
end
end
return new_string.strip
end
> translate("apple orange mango")
=> "appleay orangeay mango"