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
, whered
is a group number, or\k<n>
, wheren
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
Getting Uninitialized Constant Error When Trying to Run Tests
What Is the Ruby Equivalent of Python's Getattr
Ruby Minitest: Suite- or Class- Level Setup
Detect If Application Was Started as Http Server or Not (Rake Task, Rconsole etc)
How to Use Controller Specific Stylesheets in Rails 3.2.1
Rails: Unable to Access Log File
Ruby Array to JSON and Rails JSON Rendering
Traversing a Hash Recursively in Ruby
Yaml Indentation for Array in Hash
Ruby Method That Returns Itself
Form_For Error Messages in Ruby on Rails
Invalid Gemspec -Illformed Requirement ["#<Yaml::Syck::Defaultkey:0Xb5F9C990> 3.2.0"]
How to Deal with Memory Leaks in Rmagick in Ruby
Notices for Sequence After Running Migration in Rails on Postgresql Application