Why doesn't this work?

hey, I am a C programmer that decided to learn Ruby. I got some
exercises to do, but I’m having some trouble in this (silly)one:

Problem Statement
Given a sentence containing multiple words, find the frequency of a
given word in that sentence.

i wrote the code below

def find_frequency(sentence, word)
array = Array.new
array << sentence.split(/ /)
array.delete_if {|i| i.to_s.downcase != word.downcase}.length
end

but it appears that (i.to_s.downcase) is always different from
(word.downcase), even if the words are the same. can someone explain it
to me, please?

ps: i solved with:
def find_frequency(sentence, word)
sentence.downcase.scan(word.downcase).length
end

is there a better solution?

thanks! :slight_smile:

On 10/19/2011 03:09 PM, raphael teller wrote:

array = Array.new
array<< sentence.split(/ /)
array.delete_if {|i| i.to_s.downcase != word.downcase}.length
end

but it appears that (i.to_s.downcase) is always different from
(word.downcase), even if the words are the same. can someone explain it
to me, please?

thanks

Hi,

array<< sentence.split(/ /) # this pushes array into array
array = sentence.split(/ /)

and

i.to_s.downcase # to_s isn’t needed

def find_frequency(sentence, word)
array = Array.new
array = sentence.split(/ /)
array.delete_if {|i| i.downcase != word.downcase}.length
end

Michal

On Wed, Oct 19, 2011 at 3:09 PM, raphael teller
[email protected]wrote:

array = Array.new
array << sentence.split(/ /)
array.delete_if {|i| i.to_s.downcase != word.downcase}.length
end

but it appears that (i.to_s.downcase) is always different from
(word.downcase), even if the words are the same. can someone explain it
to me, please?

The problem is the way you store the split sentence. The return value of
split is an array and you are storing that array into the empty array,
so
inside the delete_if loop you are dealing with the whole array of words,
not
individual words. Now calling to_s on an array will return a string that
contains all the elements from that array, concatenated. Obviously this
string will not match any single word.

s = “This is a test of this”
=> “This is a test of this”
a = s.split(/ /)
=> [“This”, “is”, “a”, “test”, “of”, “this”]
a.to_s
=> “Thisisatestofthis”

By the way, you don’t need to call Array.new to create a new empty
array.
The following is equivalent:

my_array = []

Regards,
Ammar

Thank you very much. Those answers were exactly what i need.

Raphael.

On Wed, Oct 19, 2011 at 10:44:37PM +0900, Ammar A. wrote:

By the way, you don’t need to call Array.new to create a new empty array.
The following is equivalent:

my_array = []

I prefer Array.new for that usage, because (in my opinion) it more
clearly communicates the intent of creating a new array waiting to be
filled. I prefer to avoid empty array literals for most purposes. Your
mileage may vary, I suppose.

In this case, Array.new isn’t needed.

IMHO a more rubyish way would be:

def find_frequency(sentence, word)
sentence.split(/ /).select { |w| w.downcase == word.downcase }.length
end

or maybe even better:

def find_frequency(sentence, word)
sentence.split(/ /).map { |w| w.downcase }.count(word.downcase)
end

On Thu, Oct 20, 2011 at 6:23 AM, Gunther D. [email protected]
wrote:

def find_frequency(sentence, word)
sentence.split(/ /).select { |w| w.downcase == word.downcase }.length
end
or maybe even better:
def find_frequency(sentence, word)
sentence.split(/ /).map { |w| w.downcase }.count(word.downcase)
end

count does accept a block, so

def find_frequency(sentence, word)
word=word.downcase
sentence.split.count{ |w| w.downcase == word}
end

On 20/10/11 16:48, botp wrote:

def find_frequency(sentence, word)
word=word.downcase
sentence.split.count{ |w| w.downcase == word}
end
Just for fun

ruby-1.9.2-p290 :001 > lorem = “On the other hand, we denounce with
righteous indignation and dislike men who are so beguiled and
demoralized by the charms of pleasure of the moment, so blinded by
desire, that they cannot foresee the pain and trouble that are bound to
ensue; and equal blame belongs to those who fail in their duty through
weakness of will, which is the same as saying through shrinking from
toil and pain. These cases are perfectly simple and easy to distinguish.
In a free hour, when our power of choice is untrammelled and when
nothing prevents our being able to do what we like best, every pleasure
is to be welcomed and every pain avoided. But in certain circumstances
and owing to the claims of duty or the obligations of business it will
frequently occur that pleasures have to be repudiated and annoyances
accepted. The wise man therefore always holds in these matters to this
principle of selection: he rejects pleasures to secure other greater
pleasures, or else he endures pains to avoid worse pains.”
=> “On the other hand, we denounce with righteous indignation and
dislike men who are so beguiled and demoralized by the charms of
pleasure of the moment, so blinded by desire, that they cannot foresee
the pain and trouble that are bound to ensue; and equal blame belongs to
those who fail in their duty through weakness of will, which is the same
as saying through shrinking from toil and pain. These cases are
perfectly simple and easy to distinguish. In a free hour, when our power
of choice is untrammelled and when nothing prevents our being able to do
what we like best, every pleasure is to be welcomed and every pain
avoided. But in certain circumstances and owing to the claims of duty or
the obligations of business it will frequently occur that pleasures have
to be repudiated and annoyances accepted. The wise man therefore always
holds in these matters to this principle of selection: he rejects
pleasures to secure other greater pleasures, or else he endures pains to
avoid worse pains.”
ruby-1.9.2-p290 :002 > def find_frequency(prose, word)
ruby-1.9.2-p290 :003?> prose.scan(/\b(#{word})\b/im).length
ruby-1.9.2-p290 :004?> end
=> nil
ruby-1.9.2-p290 :005 > find_frequency(lorem, “selection”)
=> 1
ruby-1.9.2-p290 :006 > find_frequency(lorem, “and”)
=> 10
ruby-1.9.2-p290 :007 > find_frequency(lorem, “frequently”)
=> 1
ruby-1.9.2-p290 :008 > find_frequency(lorem, “that”)
=> 3

Sam

On 20/10/11 17:36, Josh C. wrote:

def find_frequency(prose, word)
regex = Regexp.new “\b#{Regexp.escape word}\b”, Regexp::IGNORECASE
prose.scan(regex).length
end

Too true! Still not too bad =]

def find_frequency(prose, word)
prose.scan(/\b(#{Regexp.escape word})\b/im).length
end

Sam

On Wed, Oct 19, 2011 at 11:29 PM, Sam D. [email protected]
wrote:

ruby-1.9.2-p290 :002 > def find_frequency(prose, word)
ruby-1.9.2-p290 :003?> prose.scan(/\b(#{word})\b/im).**length
ruby-1.9.2-p290 :004?> end

This was my approach, too. But by the time you make it robust, it’s no
longer elegant. i.e. it should really be escaped, leading to:

def find_frequency(prose, word)
regex = Regexp.new “\b#{Regexp.escape word}\b”, Regexp::IGNORECASE
prose.scan(regex).length
end