6572fa57acbc8588e27f95f2592d9048

Capitalizes the first letter of each word in a string... I'm a complete Ruby neophyte and am interested in comments on this: I enjoy the upcase, downcase, and capitalize built-ins, but would also like a "titlecaps" function that capitalizes the first letter of each word in a string. (Words are separated by a space.) I'm just fiddling around. Better ways to do it? More Ruby-like ways?

class String
  
  def titlecap
    newstr = self.dup
    do_titlecap(newstr)
  end

  def titlecap!
    newstr = self
    do_titlecap(newstr)
  end

  def do_titlecap(newstr)
    # First character will always be upcased
    newstr[0] = newstr[0].upcase
    
    # Go through each char - when finding a space, capitalize the following char
    c = 0
    until c == size
      if newstr[c] == " "
        newstr[c+1] = newstr[c+1].upcase
      end
      c += 1
    end
    
    newstr
  end
end

str = "edgar allan poe"

capstr = str.titlecap
puts str       # edgar allan poe
puts capstr    # Edgar Allan Poe

str.titlecap!
puts str       # Edgar Allan Poe

Refactorings

No refactoring yet !

D41d8cd98f00b204e9800998ecf8427e

d

October 5, 2010, October 05, 2010 21:36, permalink

No rating. Login to rate!

look at titleize in activesupport (either include that or take a look at the source for Inflector.titleize)

24711c3df84f635ee2c67369094c17be

sl_bug

October 5, 2010, October 05, 2010 21:48, permalink

1 rating. Login to rate!

try this method. there is only one problem. when string have 2 or more spaces in a row, result string will have only one space.

def titlecap
  self.dup.split(' ').map{|e| e.capitalize}.join(' ')
end
32953234209cc7a2e4769efe5020961e

Bryan Thompson

October 6, 2010, October 06, 2010 01:17, permalink

2 ratings. Login to rate!

Your split can be made more tolerant of spacing weirdness by using regex. I'm sure it can probably be fancied up further by not running capitalize on non-word segments.

def titlecap
  self.dup.split(/\W+/).map{|e| e.capitalize}.join(' ')
end
6572fa57acbc8588e27f95f2592d9048

SmackTurtle

October 6, 2010, October 06, 2010 14:12, permalink

No rating. Login to rate!

These are great - thanks! Seems like the 'dup' part doesn't make any difference. Without it, self still isn't modified in place. Not sure how to get my bang equivalent to work with the split/map/join. Interestingly, it works the way I originally did it, so I still have some scratchmarks on my head.

A8d3f35baafdaea851914b17dae9e1fc

Adam

October 6, 2010, October 06, 2010 17:26, permalink

1 rating. Login to rate!
class String
  def titlecap
    dup.titlecap!
  end
  
  def titlecap!
    gsub!(/(\S+)/) { $1.capitalize }
  end
end
8f6f95c4bd64d5f10dfddfdcd03c19d6

Rick DeNatale

October 6, 2010, October 06, 2010 18:39, permalink

2 ratings. Login to rate!

This can be done with gsub and gsub! just upcase any letters immediately after a \b (word break)

This code matches your test cases, but there are some potential subtleties. For example in a title in English, articles like the, an, and a are normally NOT upcased unless they are the first word.

class String
  
  def titlecap
    gsub(/\b[a-z]/) {|m| m.upcase}
  end

  def titlecap!
    gsub!(/\b[a-z]/) {|m| m.upcase}
    self
  end
end

str = "edgar allan poe"

capstr = str.titlecap
str           # => "edgar allan poe"
capstr        # => "Edgar Allan Poe"
str           # => "edgar allan poe"

str.titlecap! # => "Edgar Allan Poe"
str           # => "Edgar Allan Poe"
6572fa57acbc8588e27f95f2592d9048

SmackTurtle

October 7, 2010, October 07, 2010 02:00, permalink

No rating. Login to rate!

The gsub way looks (to quote my late grandmother) slick as a gut. Thank you for contributing to my Ruby literacy. I'm having fun. :-) I appreciate your time.

Your refactoring





Format Copy from initial code

or Cancel