How to Convert a String to Lower or Upper Case in Ruby

How to convert a string to lower or upper case in Ruby

Ruby has a few methods for changing the case of strings. To convert to lowercase, use downcase:

"hello James!".downcase    #=> "hello james!"

Similarly, upcase capitalizes every letter and capitalize capitalizes the first letter of the string but lowercases the rest:

"hello James!".upcase      #=> "HELLO JAMES!"
"hello James!".capitalize #=> "Hello james!"
"hello James!".titleize #=> "Hello James!" (Rails/ActiveSupport only)

If you want to modify a string in place, you can add an exclamation point to any of those methods:

string = "hello James!"
string.downcase!
string #=> "hello james!"

Refer to the documentation for String for more information.

How to convert lowercase string to uppercase and vice versa?

As another pointed out, swapcase already exists, but I suspect it's something you're meant to implement on your own

Here's a functional approach

class String
def is_upper?
self == self.upcase
end

def is_lower?
self == self.downcase
end

def head
self[0]
end

def tail
self[1..-1]
end

def swapcase
if empty?
""
elsif head.is_lower?
head.upcase + tail.swapcase
elsif head.is_upper?
head.downcase + tail.swapcase
else
head + tail.swapcase
end
end
end

puts "abcdE".swapcase
#=> ABCDe

The looping pattern in swapcase is pretty obnoxious and should be decomposed out into a generic function

class String
def is_upper?
self == self.upcase
end

def is_lower?
self == self.downcase
end

def head
self[0]
end

def tail
self[1..-1]
end

def map &f
if empty?
""
else
yield(head) + tail.map(&f)
end
end

def swapcase
map do |x|
if x.is_lower?
x.upcase
elsif x.is_upper?
x.downcase
else
x
end
end
end
end

It works the same but swapcase is a lot nicer now

puts "abcdE".swapcase
#=> ABCDe

Simpler way to alternate upper and lower case words in a string

You could reduce the number of lines in the each_with_index block by using a ternary conditional (true/false ? value_if_true : value_if_false):

words.each.with_index do |word, i|
newstr << i.even? ? word.upcase : word.downcase
end

As for a different way altogether, you could iterate over the initial string, letter-by-letter, and then change the method when you hit a space:

def alternating_case(str)
@downcase = true
new_str = str.map { |letter| set_case(letter)}
end

def set_case(letter)
@downcase != @downcase if letter == ' '
return @downcase ? letter.downcase : letter.upcase
end

Converting upper-case string into title-case using Ruby

While trying to come up with my own method (included below for reference), I realized that there's some pretty nasty corner cases. Better just use the method already provided in Facets, the mostest awesomest Ruby library evar:

require 'facets/string/titlecase'

class String
def titleize
split(/(\W)/).map(&:capitalize).join
end
end

require 'test/unit'
class TestStringTitlecaseAndTitleize < Test::Unit::TestCase
def setup
@str = "i just saw \"twilight: new moon\", and man! it's crap."
@res = "I Just Saw \"Twilight: New Moon\", And Man! It's Crap."
end
def test_that_facets_string_titlecase_works
assert_equal @res, @str.titlecase
end
def test_that_my_own_broken_string_titleize_works
assert_equal @res, @str.titleize # FAIL
end
end

If you want something that more closely complies to typical writing style guidelines (i.e. does not capitalize words like "and"), there are a couple of "titleize" gems on GitHub.

How to lowercase only the first character of a string in Ruby?

One way:

str = "Hello World"
str[0] = str[0].downcase
str #=> "hello World"

How to change case of letters in string using RegEx in Ruby

@sawa Has the simple answer, and you've edited your question with another mechanism. However, to answer two of your questions:

Is there a way to do this within the regex though?

No, Ruby's regex does not support a case-changing feature as some other regex flavors do. You can "prove" this to yourself by reviewing the official Ruby regex docs for 1.9 and 2.0 and searching for the word "case":

  • https://github.com/ruby/ruby/blob/ruby_1_9_3/doc/re.rdoc
  • https://github.com/ruby/ruby/blob/ruby_2_0_0/doc/re.rdoc

I don't really understand the '\1' '\2' thing. Is that backreferencing? How does that work?

Your use of \1 is a kind of backreference. A backreference can be when you use \1 and such in the search pattern. For example, the regular expression /f(.)\1/ will find the letter f, followed by any character, followed by that same character (e.g. "foo" or "f!!").

In this case, within a replacement string passed to a method like String#gsub, the backreference does refer to the previous capture. From the docs:

"If replacement is a String it will be substituted for the matched text. It may contain back-references to the pattern’s capture groups of the form \d, where d is a group number, or \k<n>, where n is a group name. If it is a double-quoted string, both back-references must be preceded by an additional backslash."

In practice, this means:

"hello world".gsub( /([aeiou])/, '_\1_' )  #=> "h_e_ll_o_ w_o_rld"
"hello world".gsub( /([aeiou])/, "_\1_" ) #=> "h_\u0001_ll_\u0001_ w_\u0001_rld"
"hello world".gsub( /([aeiou])/, "_\\1_" ) #=> "h_e_ll_o_ w_o_rld"

Now, you have to understand when code runs. In your original code…

string.gsub!(/([a-z])([A-Z]+ )/, '\1'.upcase)

…what you are doing is calling upcase on the string '\1' (which has no effect) and then calling the gsub! method, passing in a regex and a string as parameters.

Finally, another way to achieve this same goal is with the block form like so:

# Take your pick of which you prefer:
string.gsub!(/([a-z])([A-Z]+ )/){ $1.upcase << $2.downcase }
string.gsub!(/([a-z])([A-Z]+ )/){ [$1.upcase,$2.downcase].join }
string.gsub!(/([a-z])([A-Z]+ )/){ "#{$1.upcase}#{$2.downcase}" }

In the block form of gsub the captured patterns are set to the global variables $1, $2, etc. and you can use those to construct the replacement string.

Ruby 1.9: how can I properly upcase & downcase multibyte strings?

Case conversion is locale dependent and doesn't always round-trip, which is why Ruby 1.9 doesn't cover it (see here and here)

The unicode-util gem should address your needs.



Related Topics



Leave a reply



Submit