Word Count (Ruby)

6.8k views Asked by At

CoderByte offers the following challenge: "Using the Ruby language, have the function WordCount(str) take the str string parameter being passed and return the number of words the string contains (ie. "Never eat shredded wheat" would return 4). Words will be separated by single spaces."

I solved it, but is there a simpler solution (that doesn't use regular expressions or methods other than .length)? I have a conditional inside of a conditional inside of a for-loop inside of a for-loop. I also set the current variable to false both inside and outside the first for-loop.

Are these poor practices? Is there a better solution?

def WordCount(string)

    alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    counter = 0
    current = false

    for i in 0...string.length
        prev = current
        current = false
        for j in 0...alphabet.length
            if string[i] == alphabet[j]
                current = true
                if prev == false
                    counter += 1
                end
            end
        end
    end

    return counter

end

WordCount(STDIN.gets)
5

There are 5 answers

3
daremkd On

The most elegant solution I've seen on finding word count in Ruby was:

words = 'This is a word'
p words.scan(/\S+/).size #=> 4

For most convenience, monkey patch String:

class String
  def number_of_words
    self.scan(/\S+/).size
  end
end

p 'Hi there, how are you?'.number_of_words #=> 5

The main problem I see with your code is that you're coding, but you aren't coding in Ruby(style). You'll rarely see people use for/in here, for example. If you know how to write idiomatic Ruby, code that would take 10 lines in other languages are barely 1 line long here.

1
Cary Swoveland On

Punctuation is obviously an issue. Aside from the apostrophe, mentioned elsewhere, old-schoolers hyphenate certain groups of words, such as compound adjectives, dashes are used to set off clauses, ellipses (e.g., the symbol ' …' or multiple periods) indicate continuation or a change of thought, slashes provide choices and so on. One way to deal with that (without using a regrex) would be to first use String#tr (or String#gsub) to convert those punctuation characters to spaces (remove ' if you want "don't" treated as one word):

def word_count str
  str.tr("'-/–…\.", ' ').split.size
end

word_count "It was the best of times, it was the worst of times"
  #=> 12 
word_count "I don't think his/her answer is best."
  #=>  9
word_count "Mozart is a much-beloved composer."   # with hyphen
  #=>  6
word_count "I pay the bills–she has all the fun." # with dash
  #=>  9
word_count "I wish you would…oh, forget it."      # with ellipse
  #=>  7
word_count "I wish you would––oh, forget it."     # with dashes
  #=>  7
word_count ""
  #=>  0

On a Mac, a dash is entered as Option, hyphen; an ellipse, Option, semi-colon (or "semicolon", both are accepted :-) ).

Now we just have to figure out how to count hyphenated words ("state-of-the-art") as a single word. Actually, I've just scratched the surface of this complex subject. Sorry if I got carried away. What was the question again?

2
Rustam Gasanov On

Hm,

s = "Never eat shredded wheat"
puts s.split.count
# => 4

If you don't want to count underscores and digits:

s = "Never eat shredded wheat 1 _ ?"
puts s.split.reject { |w| w =~ /(\W|_|\d)/ }.count
# => 4

even more advanced regexp:

s = "Never __ 111 ?? eat shredded wheat. _Word?"
p s.split.reject { |w| w !~ /([a-zA-Z]+(_[a-zA-Z]+)*)/ }
# => ["Never", "eat", "shredded", "wheat.", "_Word?"]
2
Agis On

It does involve regular expressions but it's the correct solution:

"Hi there 334".scan(/[[:alpha:]]+/).count # => 2
0
Darkmouse On
string = ''              => Your string will be stored in this variable
word_count = string.split(' ').count

This should solve it.