1
let str = "tHIS is A test"
let swapped_case = "This IS a TEST"

Swift noob here, how to do the second statement programatically?

jscs
  • 63,694
  • 13
  • 151
  • 195
Kaatt
  • 1,061
  • 1
  • 8
  • 10

6 Answers6

6

This function works with all upper/lowercase characters defined in Unicode, even those from "foreign" languages such as Ä or ć:

func swapCases(_ str : String) -> String {
    var result = ""
    for c in str.characters { // Swift 1: for c in str {
        let s = String(c)
        let lo = s.lowercased() //Swift 1 & 2: s.lowercaseString
        let up = s.uppercased() //Swift 1 & 2: s.uppercaseString
        result += (s == lo) ? up : lo
    }
    return result
}

Example:

let str = "tHIS is a test ÄöÜ ĂćŒ Α" // The last character is a capital Greek Alpha
let swapped_case = swapCases(str)
print(swapped_case)
// This IS A TEST äÖü ăĆœ α
XW_
  • 472
  • 1
  • 5
  • 11
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
2

Use switch statement in-range checks to determine letter case, and use NSString-bridged methods to convert accordingly.

let str = "tHIS is A test"
let swapped_case = "This IS a TEST"

func swapCase(string: String) -> String {
    var swappedCaseString: String = ""
    for character in string {
        switch character {
        case "a"..."z":
            let uppercaseCharacter = (String(character) as NSString).uppercaseString
            swappedCaseString += uppercaseCharacter
        case "A"..."Z":
            let lowercaseCharacter = (String(character) as NSString).lowercaseString
            swappedCaseString += lowercaseCharacter
        default:
            swappedCaseString += String(character)
        }
    }

    return swappedCaseString
}

swapCase(str)
mattt
  • 19,544
  • 7
  • 73
  • 84
1

I'm a bit too late but this works too :-)

let str = "tHIS is A test"
var res = ""
for c in str {
  if contains("ABCDEFGHIJKLMNOPQRSTUVWXYZ", c) {
    res += "\(c)".lowercaseString
  } else {
    res += "\(c)".uppercaseString
  }
}
res
qwerty_so
  • 35,448
  • 8
  • 62
  • 86
1

In Swift 5 I achieved it by creating a function which iterates through each character of the string, and using string methods to change each character I appended each character back into a new variable:

func reverseCase(string: String) -> String {
    var newCase = ""
    for char in string {
        if char.isLowercase {
            newCase.append(char.uppercased())
        }
        else if char.isUppercase {
            newCase.append(char.lowercased())
        }
        else {
            newCase.append(char)
        }
    }
    return newCase
}

Then just pass your string through to the function when you call it in a print statement:

print(reverseCase(string: str))

nickalara
  • 41
  • 3
0

You already have plenty of good succinct answers but here’s an over-elaborate one for fun.

Really this is a job for map – iterate over a collection (in this case String) and do a thing to each element (here, each Character). Except map takes any collection, but only gives you back an array, which you’d have to then turn into a String again.

But here’s a version of map that, given an extensible collection, gives you back that same kind of extensible collection.

(It does have the limitation of needing both collections to contain the same type, but that’s fine for strings. You could make it return a different type, but then you’d have to tell it which type you wanted i.e. map(s, transform) as String which would be annoying)

func map<C: ExtensibleCollectionType>(source: C, transform: (C.Generator.Element) -> C.Generator.Element) -> C {
    var result = C()

    for elem in source {
        result.append(transform(elem))
    }

    return result
}

Then to write the transform function, first here’s an extension to character similar to the other answers. It does seem quite unsatisfying that you have to convert to a string just to uppercase a character, is there really no good (international characterset-friendly) way to do this?

extension Character {
    var uppercaseCharacter: Character {
        let s = String(self).uppercaseString
        return s[s.startIndex]
    }

    var lowercaseCharacter: Character {
        let s = String(self).lowercaseString
        return s[s.startIndex]
    }
}

And the function to flip the case. What I wonder is whether this pattern matching is international-friendly. It seems to be – "A"..."Z" ~= "Ä" returns true.

func flipCase(c: Character) -> Character {
    switch c {
    case "A"..."Z":
        return c.lowercaseCharacter
    case "a"..."z":
        return c.uppercaseCharacter
    default:
        return c
    }
}

Finally:

let s = map("Hello", flipCase)
// s is a String = "hELLO"
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • `case "A"..."Z"` matches "Ä" and "Ć", but not "Œ" or "Α" (U+0391, GREEK CAPITAL LETTER ALPHA) . And the uppercase string of a single character can actually be more than one character, e.g. `"ß".uppercaseString == "SS"` ! – Martin R Jan 31 '15 at 20:49
  • Aha, thanks, shows what I know! Interesting that it can expand single chars to multiple, perhaps it’s a job for flatMap :-) Is it ever appropriate to go the other way i.e. if presented with “SS”, map to “ß”? Or is it never that unambiguous? – Airspeed Velocity Jan 31 '15 at 20:56
  • "SS" *is* ambiguous (in the German language). It could be the upper case of "ss" or of "ß". – There is actually a Unicode character "ẞ" U+1E9E LATIN CAPITAL LETTER SHARP S, but I have never seen that being used. Interestingly, `"\u{1E9E}".lowercaseString == "ß"` is true, but `"ß".uppercaseString == "\u{1E9E}"` is false. And the [Unicode Database](http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt) does not define an uppercase character for ß (U+00DF). – To make it short: I don't know the exact conversion rules, but it seems that the conversions are sometimes not reversible. – Martin R Jan 31 '15 at 21:11
  • Btw., "Ä" matches "A" ... "Z" because it can be *decomposed* into "A" plus a combining diacritical mark. There is no similar decomposition for "Œ" (and many more international letters). String comparison is done based on a canonical decomposition, I made some investigations here: http://stackoverflow.com/a/25775112/1187415. – Martin R Jan 31 '15 at 21:13
  • Thanks for that linked answer, it was very informative and explained several things I had wondered about. – Airspeed Velocity Jan 31 '15 at 22:02
0

I hope this helps. inputString and resultString are the input and output respectively.

let inputString = "Example"

let outputString = inputString.characters.map { (character) -> Character in
    let string = String(character)
    let lower = string.lowercased()
    let upper = string.uppercased()
    return (string == lower) ? Character(upper) : Character(lower)
}

let resultString = String(outputString)
Vasanth
  • 24
  • 8