rubyguides

String#swapcase

str.swapcase(*options) → string

String#swapcase returns a new string with the case of each character reversed. Every uppercase character becomes lowercase, and every lowercase character becomes uppercase. This is useful for stylistic transformations, display formatting, or when you need to toggle case without normalizing to a specific case.

Syntax

str.swapcase
str.swapcase(*options)

The optional options parameter accepts symbols that change how Unicode characters are handled.

Basic Usage

"Hello".swapcase
# => "hELLO"

"world".swapcase
# => "WORLD"

"RuBy".swapcase
# => "rUbY"

The original string is never modified:

original = "Hello"
result = original.swapcase

original
# => "Hello"

result
# => "hELLO"

Non-alphabetic characters are left unchanged:

"123abc!@#".swapcase
# => "123ABC!@#"

"foo.bar".swapcase
# => "FOO.BAR"

Unicode Case Mapping

From Ruby 3.0 onward, swapcase uses full Unicode case mapping by default. This means accented characters and non-ASCII letters are handled:

"Über".swapcase
# => "üBER"

"Ångström".swapcase
# => "åNGSTRÖM"

"Straße".swapcase
# => "sTRASSEN"

Characters that have no case variant stay unchanged:

"123".swapcase
# => "123"

ASCII-Only Conversion

Use :ascii when you only want a-z and A-Z swapped, leaving all other characters untouched:

"Über".swapcase
# => "üBER"

"Über".swapcase(:ascii)
# => "üBER"

In this case, ü and Ö are outside the ASCII range, so they are not affected. The :ascii option is useful when you are working with mixed encodings or when non-ASCII characters should be preserved as-is.

Turkic Case Mapping

Turkish distinguishes dotted and dotless I. Use :turkic when processing Turkish text:

"ID".swapcase
# => "id"

"ID".swapcase(:turkic)
# => "ıd"

The standard swapcase converts I to ı (lowercasing) and D to d, giving "ıd". With :turkic, Ruby applies the correct Unicode case mapping for Turkish — uppercase dotted I (U+0130) becomes lowercase dotless ı (U+0131), not a regular i.

In-Place Swapping

Use swapcase! when you want to mutate the receiver:

text = "Hello"
text.swapcase!
# => "hELLO"

text
# => "hELLO"

swapcase! returns self if changes were made, or nil if the string was already in the target case:

"hello".swapcase!
# => "HELLO"

"HELLO".swapcase!
# => nil

Common Patterns

Toggle case for display

labels = ["name", "Email", "Phone"]
labels.map(&:swapcase)
# => ["NAME", "eMAIL", "pHONE"]

Process mixed-case identifiers

def normalize_id(id)
  id.swapcase
end

normalize_id("User123")
# => "uSER123"

Check case-swapped equality

a = "Hello"
b = "hELLO"

a.swapcase == b
# => true

Edge Cases

Empty strings

"".swapcase
# => ""

No alphabetic characters

"123!@#".swapcase
# => "123!@#"

Turkish locale sensitivity

The Turkish locale has unusual case-mapping rules for I and İ. Always use :turkic when processing Turkish text to get correct results:

# Standard behavior (wrong for Turkish):
"İstanbul".swapcase
# => "ıSTANBUL"  — dotted İ becomes ı, but should become i

# With Turkic option (correct for Turkish):
"İstanbul".swapcase(:turkic)
# => "i̇stanbul"  — dotted İ becomes i with combining dot above

Characters without case mapping

Some Unicode characters do not have a case variant. These pass through unchanged:

"日本".swapcase
# => "日本"

See Also