How to replace text in a ruby string - ruby

I am trying to write a very simple method in Ruby which takes a string and an array of words and checks if the string contains any of the words and if it does it replaces them with their uppercase.
I made an attempt but its not great due to my level of Ruby skills.
def(my_words,my_sentence)
#split the sentence up into an array of words
my_sentence_words = my_sentence.split(/\W+/)
#nested loop that checks the words array for each brand
my_sentence_words.each do |i|
my_words.each do |i|
#if it finds a brand in the words and sets them to be uppercase
if my_words[i] == my_sentence_words[i]
my_sentence_words[i] == my_sentence_words[i].up.case
end
end
end
#put the words array into one string
words.each do |i|
new_sentence = ("" + my_sentence_words[i]) + " "
end
end
I am getting: can't convert string into integer error

def convert(mywords,sentence)
regex = /#{mywords.join("|")}/i
sentence.gsub(regex) { |m| m.upcase }
end
convert(%W{ john james jane }, "I like jane but prefer john")
#=> "I like JANE but prefer JOHN"

This will work better. It loops through the brands, searches for each, and replaces with the uppercase version.
brands = %w(sony toshiba)
sentence = "This is a sony. This is a toshiba."
brands.each do |brand|
sentence.gsub!(/#{brand}/i, brand.upcase)
end
Results in the string.
"This is a SONY. This is a TOSHIBA."
For those who like Ruby foo!
sentence.gsub!(/#{brands.join('|')}/i) { |b| b.upcase }
And in a function
def capitalize_brands(brands, sentence)
sentence.gsub(/#{brands.join('|')}/i) { |b| b.upcase }
end

You get this error because i doesn't start from 0 as you expected, in each method i is an element of array, and has string type, it's a first word from your sentence:
my_sentence_words = ["word"]
my_sentence_words.each do |i|
puts i.length #=> 4
puts i.type #=> String
puts i #=> word
end
So you try to call my_sentence_words[word] instead of my_sentence_words[0]. You can try method each_index that passes index of element instead of element itself`:
def check(str, *arr)
upstr = str.split(' ')
upstr.eachindex do |i| #=> i is index
arr.each_index do |j|
upstr[i].upcase! if upstr[i] == arr[j]
end
end
upstr
end
check("This is my sentence", "day", "is", "goal", "may", "my")
#=>["This", "IS", "MY", "sentence"]

Related

Chop last character of string

I want to make program which takes the string and chop last character each time and print result to console:
With an input string of Hello, the result should be:
Hello
Hell
Hel
He
H
This is my code so far:
def test_string
puts "Put your string in: "
string = gets.chomp
while string.length == 0
puts string.chop(/.$/)
end
end
puts test_string
Use chop!:
string = gets.chomp
# Print full string, e.g. "Hello"
puts string
# Print remaining... e.g. "Hell", "Hel", etc.
while string.length != 0
puts string.chop!
end
Following code does not modify the original string
string = gets.chomp
l = string.length
l.times do |i|
puts string[0..(l-i-1)]
end
You can also create an array filling it with the string N times, and for each time, get a character less from it:
str = 'Hello'
Array.new(str.size) { |index| str[0...str.size - index] }.each { |str| p str }
# "Hello"
# "Hell"
# "Hel"
# "He"
# "H

Ruby method that uppercases even indexed letters and lowercases odd

Directions:
Write a method that accepts a string, and returns the same string with all even indexed characters in each word upper cased, and all odd indexed characters in each word lower cased. The indexing just explained is zero based, so the zero-ith index is even, therefore that character should be upper cased.
The passed in string will only consist of alphabetical characters and spaces(' '). Spaces will only be present if there are multiple words. Words will be separated by a single space(' ').
My code:
(someone please refactor or explain to me a cleaner/shorter solution)
def weirdcase(string)
arr = string.split(' ')
arr.map! {|word|
char = word.chars
char.each_with_index do |letter, i|
i % 2 == 0 ? letter.upcase! : letter.downcase!
end
}
arr.map! {|a| a.push(' ').join('')}
x = arr.join('').to_s
x[0...-1]
end
This is one way you could do that, using Array#cycle to create an enumerator and String#gsub to replace every character in the string with its value upcased or downcased.
def weirdcase(str)
enum = [:upcase, :downcase].cycle
str.gsub(/./) do |s|
if s == ' '
enum.rewind
s
else
s.public_send(enum.next)
end
end
end
weirdcase "Mary had a little lamb"
#=> "MaRy hAd a lItTlE LaMb"
By making gsub's argument /./ each character in the string is replaced by the value returned by the block, which, if that character is not a space, is that character either upcased or downcased, depending on the symbol generated by the enumerator enum, which alternates between :upcase and :downcase for each word.
Note that
enum = [:upcase, :downcase].cycle
#=> #<Enumerator: [:upcase, :downcase]:cycle>
enum.next
#=> :upcase
enum.next
#=> :downcase
enum.next
#=> :upcase
and so on. See also Enumerator#next.
Enumerator#rewind is needed to begin anew the alternating of case with each word.
One could replace s.public_send(enum.next) with
enum.next == :upcase ? s.upcase : s.downcase
You could also use gsub to change two adjacent characters at a time:
def weirdcase(string)
string.gsub(/(.)(.?)/) { "#{$1.upcase}#{$2.downcase}" }
end
weirdcase "Mary had a little lamb"
#=> "MaRy hAd a lItTlE LaMb"
The ? makes the second character optional, which is needed for odd-length strings:
weirdcase "foo"
#=> "FoO"
Or a using each_char and with_index:
def weirdcase(string)
string.each_char.map.with_index { |char, index|
if index.odd?
char.downcase
else
char.upcase
end
}.join
end
If you want to change each word separately:
"Mary had a little lamb".split(' ').map { |word| weirdcase(word) }.join(' ')
#=> "MaRy HaD A LiTtLe LaMb"
or again with gsub:
"Mary had a little lamb".gsub(/\S+/) { |word| weirdcase(word) }
#=> "MaRy HaD A LiTtLe LaMb"

Ruby getting the longest word of a sentence

I'm trying to create method named longest_word that takes a sentence as an argument and The function will return the longest word of the sentence.
My code is:
def longest_word(str)
words = str.split(' ')
longest_str = []
return longest_str.max
end
The shortest way is to use Enumerable's max_by:
def longest(string)
string.split(" ").max_by(&:length)
end
Using regexp will allow you to take into consideration punctuation marks.
s = "lorem ipsum, loremmm ipsummm? loremm ipsumm...."
first longest word:
s.split(/[^\w]+/).max_by(&:length)
# => "loremmm"
# or using scan
s.scan(/\b\w+\b/).max_by(&:length)
# => "loremmm"
Also you may be interested in getting all longest words:
s.scan(/\b\w+\b/).group_by(&:length).sort.last.last
# => ["loremmm", "ipsummm"]
It depends on how you want to split the string. If you are happy with using a single space, than this works:
def longest(source)
arr = source.split(" ")
arr.sort! { |a, b| b.length <=> a.length }
arr[0]
end
Otherwise, use a regular expression to catch whitespace and puntuaction.
def longest_word(sentence)
longest_word = ""
words = sentence.split(" ")
words.each do |word|
longest_word = word unless word.length < longest_word.length
end
longest_word
end
That's a simple way to approach it. You could also strip the punctuation using a gsub method.
Funcional Style Version
str.split(' ').reduce { |r, w| w.length > r.length ? w : r }
Another solution using max
str.split(' ').max { |a, b| a.length <=> b.length }
sort_by! and reverse!
def longest_word(sentence)
longw = sentence.split(" ")
longw.sort_by!(&:length).reverse!
p longw[0]
end
longest_word("once upon a time long ago a very longword")
If you truly want to do it in the Ruby way it would be:
def longest(sentence)
sentence.split(' ').sort! { |a, b| b.length <=> a.length }[0]
end
This is to strip the word from the extra chars
sen.gsub(/[^0-9a-z ]/i, '').split(" ").max_by(&:length)
Find Longest word in a string
sentence = "Hi, my name is Mesut. There is longestword here!"
def longest_word(string)
long = ""
string.split(" ").each do |sent|
if sent.length >= long.length
long = sent
end
end
return long
end
p longest_word(sentence)

Match a pattern in an array

There is an array with 2 elements
test = ["i am a boy", "i am a girl"]
I want to test if a string is found inside the array elements, say:
test.include("boy") ==> true
test.include("frog") ==> false
Can i do it like that?
Using Regex.
test = ["i am a boy" , "i am a girl"]
test.find { |e| /boy/ =~ e } #=> "i am a boy"
test.find { |e| /frog/ =~ e } #=> nil
Well you can grep (regex) like this:
test.grep /boy/
or even better
test.grep(/boy/).any?
Also you can do
test = ["i am a boy" , "i am a girl"]
msg = 'boy'
test.select{|x| x.match(msg) }.length > 0
=> true
msg = 'frog'
test.select{|x| x.match(msg) }.length > 0
=> false
I took Peters snippet and modified it a bit to match on the string instead of the array value
ary = ["Home:Products:Glass", "Home:Products:Crystal"]
string = "Home:Products:Glass:Glasswear:Drinking Glasses"
USE:
ary.partial_include? string
The first item in the array will return true, it does not need to match the entire string.
class Array
def partial_include? search
self.each do |e|
return true if search.include?(e.to_s)
end
return false
end
end
If you don't mind to monkeypatch the the Array class you could do it like this
test = ["i am a boy" , "i am a girl"]
class Array
def partial_include? search
self.each do |e|
return true if e[search]
end
return false
end
end
p test.include?("boy") #==>false
p test.include?("frog") #==>false
p test.partial_include?("boy") #==>true
p test.partial_include?("frog") #==>false
If you want to test if a word included into the array elements, you can use method like this:
def included? array, word
array.inject([]) { |sum, e| sum + e.split }.include? word
end

How to get words frequency in efficient way with ruby?

Sample input:
"I was 09809 home -- Yes! yes! You was"
and output:
{ 'yes' => 2, 'was' => 2, 'i' => 1, 'home' => 1, 'you' => 1 }
My code that does not work:
def get_words_f(myStr)
myStr=myStr.downcase.scan(/\w/).to_s;
h = Hash.new(0)
myStr.split.each do |w|
h[w] += 1
end
return h.to_a;
end
print get_words_f('I was 09809 home -- Yes! yes! You was');
This works but I am kinda new to Ruby too. There might be a better solution.
def count_words(string)
words = string.split(' ')
frequency = Hash.new(0)
words.each { |word| frequency[word.downcase] += 1 }
return frequency
end
Instead of .split(' '), you could also do .scan(/\w+/); however, .scan(/\w+/) would separate aren and t in "aren't", while .split(' ') won't.
Output of your example code:
print count_words('I was 09809 home -- Yes! yes! You was');
#{"i"=>1, "was"=>2, "09809"=>1, "home"=>1, "yes"=>2, "you"=>1}
def count_words(string)
string.scan(/\w+/).reduce(Hash.new(0)){|res,w| res[w.downcase]+=1;res}
end
Second variant:
def count_words(string)
string.scan(/\w+/).each_with_object(Hash.new(0)){|w,h| h[w.downcase]+=1}
end
def count_words(string)
Hash[
string.scan(/[a-zA-Z]+/)
.group_by{|word| word.downcase}
.map{|word, words|[word, words.size]}
]
end
puts count_words 'I was 09809 home -- Yes! yes! You was'
This code will ask you for input and then find the word frequency for you:
puts "enter some text man"
text = gets.chomp
words = text.split(" ")
frequencies = Hash.new(0)
words.each { |word| frequencies[word.downcase] += 1 }
frequencies = frequencies.sort_by {|a, b| b}
frequencies.reverse!
frequencies.each do |word, frequency|
puts word + " " + frequency.to_s
end
This works, and ignores the numbers:
def get_words(my_str)
my_str = my_str.scan(/\w+/)
h = Hash.new(0)
my_str.each do |s|
s = s.downcase
if s !~ /^[0-9]*\.?[0-9]+$/
h[s] += 1
end
end
return h
end
print get_words('I was there 1000 !')
puts '\n'
You can look at my code that splits the text into words. The basic code would look as follows:
sentence = "Ala ma kota za 5zł i 10$."
splitter = SRX::Polish::WordSplitter.new(sentence)
histogram = Hash.new(0)
splitter.each do |word,type|
histogram[word.downcase] += 1 if type == :word
end
p histogram
You should be careful if you wish to work with languages other than English, since in Ruby 1.9 the downcase won't work as you expected for letters such as 'Ł'.
class String
def frequency
self.scan(/[a-zA-Z]+/).each.with_object(Hash.new(0)) do |word, hash|
hash[word.downcase] += 1
end
end
end
puts "I was 09809 home -- Yes! yes! You was".frequency

Resources