yeyo
yeyo

Reputation: 3009

How can I identify uppercase and lowercase characters in a string with swift?

This is what I have so far (for testing purpose):

let string = "The quick BroWn fOX jumpS Over tHe lazY DOg"

for chr in string {
    if isupper(String(chr)) {
        print(String(chr).lowercaseString)
        continue
    }
    print(chr)
}

how can I test for uppercase and lowercase characters?

I know I can call C functions from swift, but this does not seems to be correct for me. How can I do this with swift only?

Upvotes: 41

Views: 39515

Answers (18)

Mohit Kumar
Mohit Kumar

Reputation: 3076

Swift 5 Check with character properties

let string = "The quick BroWn fOX jumpS Over tHe lazY DOg"
for (_,ch) in string.enumerated() {
    if ch.isUppercase {
         //uppercase
   } else {
        //lowercase: ch.isLowercase
   }
}

Swift 4 Enumerate a string and get ascii code for character and then compare.

ascii code for

a -> 97 b -> 98 ...

A -> 65 B -> 66 ...

let string = "The quick BroWn fOX jumpS Over tHe lazY DOg"
for (_,ch) in string.enumerated() {
    let chValue = String(ch).unicodeScalars
    let asciiValue = chValue[chValue.startIndex].value
    if asciiValue >= 97 {
           //lowercase
    } else {
           //uppercase
    }
}

Upvotes: 2

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119108

Simple extension accepts any CharacterSet to check:

extension String {
    func hasCharacter(in characterSet: CharacterSet) -> Bool {
        return rangeOfCharacter(from: characterSet) != nil
    }
}

usage:

"aBc".hasCharacter(in: .lowercaseLetters)
"aBc".hasCharacter(in: .uppercaseLetters)
"aBc".hasCharacter(in: <#AnyOtherCharacterSetYouWant#>)

Upvotes: 3

Thanh Pham
Thanh Pham

Reputation: 2090

In Swift 5, we can now check for character properties per Unicode standard.

For your question, chr.isUppercase and chr.isLowercase is the answer.

Upvotes: 22

HelloimDarius
HelloimDarius

Reputation: 695

Just to check if string contains Upper, Lower or Special characters:

let lowerCase = CharacterSet.lowercaseLetters
let upperCase = CharacterSet.uppercaseLetters
let numbers = CharacterSet.decimalDigits

let containsNumbers = text.unicodeScalars.contains(where: { numbers.contains($0) })
let containsLowerCase = text.unicodeScalars.contains(where: { lowerCase.contains($0) })
let containsUpperCase = text.unicodeScalars.contains(where: { upperCase.contains($0) })
let containsSpecial = text.unicodeScalars.contains(where: { !lowerCase.contains($0) && !upperCase.contains($0) && !numbers.contains($0) })

Upvotes: 0

AndyRoid
AndyRoid

Reputation: 5057

SWIFT 4:

You can simply just do no need for all the other fancy stuff unless you are checking for numerals or unicode scalars, etc.:

extension String {

   var isLowercase: Bool {
       return self == self.lowercased()
   }

   var isUppercase: Bool {
       return self == self.uppercased()
   }

}

Upvotes: 6

Musa almatri
Musa almatri

Reputation: 5842

Simple Swifty extension :

extension String {
    var isLower: Bool {
        return String(self.filter { String($0) == String($0).lowercased() }) == self
    }
}

Upvotes: 0

R OMS
R OMS

Reputation: 662

Add this Swift extension so that all instances of Character class have two new functions: isUpperCase() to test if the character is upper case and isLowerCase() to test if the character is lower case. The implementation simply checks to see if the character instance is in the required set.

extension Character {

        func isUpperCase() -> Bool {
            return CharacterSet.uppercaseLetters.contains(self.unicodeScalars.first!)
        }

        func isLowerCase() -> Bool {
            return CharacterSet.lowercaseLetters.contains(self.unicodeScalars.first!)
        }

  }

Upvotes: 2

nicksweet
nicksweet

Reputation: 3999

Swift 3:

var str = "Hello"

let upperChars = str.unicodeScalars.flatMap({ char in
    CharacterSet.uppercaseLetters.contains(char) ? char : nil
})

let lowerChars = str.unicodeScalars.flatMap({ char in
    CharacterSet.lowercaseLetters.contains(char) ? char : nil
})

// upperChars -> ["H"]
// lowerChars -> ["e", "l", "l", "o"]

Upvotes: 0

cypher
cypher

Reputation: 111

create and use this extension:

extension Character {
        var isUppercase: Bool {
            return (String(self).unicodeScalars.filter {
                $0.value >= "A".unicodeScalars.first!.value &&
                $0.value <= "Z".unicodeScalars.first!.value
            }).count != 0
        }
    }

Upvotes: 0

cypher
cypher

Reputation: 111

create and use this extension:

extension Character {
    var isUppercase: Bool {
        guard self.asciiValue != nil else {
            return false
        }

        return self.asciiValue! >= Character("A").asciiValue! &&
                self.asciiValue! <= Character("Z").asciiValue!
    }

    var asciiValue: UInt32? {
        return String(self).unicodeScalars.first?.value
    }
}

Upvotes: 1

guidos
guidos

Reputation: 542

I am not sure what you mean by trying to avoid C functions. I hope this does not include avoiding the frameworks and foundational libraries that OS X and iOS offer you when developing an app, like, for instance, the NSCharacterSet class which provides exactly what you need in a Unicode compatible implementation.

To expand on Matt's answer, bringing it a little closer to your question's requirements:

import UIKit

let testString = "Åke röstet un café in Владивосток!"
let lowerCase = NSCharacterSet.lowercaseLetterCharacterSet()
let upperCase = NSCharacterSet.uppercaseLetterCharacterSet()

for currentCharacter in testString.utf16 {
  if lowerCase.characterIsMember(currentCharacter) {
    println("Character code \(currentCharacter) is lowercase.")
  } else if upperCase.characterIsMember(currentCharacter) {
    println("Character code \(currentCharacter) is UPPERCASE.")
  } else {
    println("Character code \(currentCharacter) is neither upper- nor lowercase.")
  }
}

Swift 3

let testString = "Åke röstet un café in Владивосток!"
let lowerCase = CharacterSet.lowercaseLetters
let upperCase = CharacterSet.uppercaseLetters

for currentCharacter in testString.unicodeScalars {
    if lowerCase.contains(currentCharacter) {
        print("Character code \(currentCharacter) is lowercase.")
    } else if upperCase.contains(currentCharacter) {
        print("Character code \(currentCharacter) is UPPERCASE.")
    } else {
        print("Character code \(currentCharacter) is neither upper- nor lowercase.")
    }
}

Upvotes: 22

Jason
Jason

Reputation: 413

In Swift 3, I do this sort of thing

import UIKit
...
let ch = "A".unicodeScalars.first!
let is_ch_upperCase = CharacterSet.uppercaseLetters.contains(ch)

Upvotes: 7

Ryan
Ryan

Reputation: 6642

By extending String and Character I think I've arrived at a fairly flexible solution that is fully(?) Unicode aware. The syntax below is for Swift 3.0. Though there is nothing here that should not be possible in Swift 2.x.

extension String {
    func isUppercased(at: Index) -> Bool {
        let range = at..<self.index(after: at)
        return self.rangeOfCharacter(from: .uppercaseLetters, options: [], range: range) != nil
    }
}

extension Character {
    var isUppercase: Bool {
      let str = String(self)
      return str.isUppercased(at: str.startIndex)
    }
}

let str = "AaÀàΓγ!2😂🇺🇸"
let uppercase = str.characters.filter({ $0.isUppercase }) // ["A", "À", "Γ"]
for char in str.characters {
    "\(char): \(char.isUppercase)"
}

// A: true
// a: false
// À: true
// à: false
// Γ: true
// γ: false
// !: false
// 2: false
// 😂: false
// 🇺🇸: false

The TODO for these extensions is to refactor isUppercase on Character to not convert to String.

Upvotes: 10

Nikolaj Boel Jensen
Nikolaj Boel Jensen

Reputation: 103

Expanding on Bob Prystaneks function, you could always extend the Swift "Character" class. Just put the following extension anywhere in your code, and now you can ask any Character if it's uppercase.

extension Character
{
    public func isUpper() -> Bool
    {
        let characterString = String(self)
        return (characterString == characterString.uppercaseString) && (characterString != characterString.lowercaseString)
    }
}

Upvotes: 4

Bob Prystanek
Bob Prystanek

Reputation: 441

As other has commented, using only uppercaseString or lowercaseString doesn't take "non-alpha" characters into account.

This is how I implemented isupper. A character is only an uppercase if it isn't equal to its lowercase.

func isupper(c:Character) -> Bool
{
    let cs = String(c)
    return (cs == cs.uppercaseString) && (cs != cs.lowercaseString)
}

Upvotes: 1

Javatar
Javatar

Reputation: 2665

Every character can be presented a UTF or Unicode value (8/16/21 Bit):

For example:

UTF-8 "Dog!": 68, 111, 103, 33
Unicode (Dog Face): U+1F436

So if you wanna check for upper and lower case, you can just match the UTF range.

(PS: Watch out for different UTF-XX/Unicode formats)

Upvotes: 0

Matt Wilding
Matt Wilding

Reputation: 20153

Cleaner, but possibly slower than looping:

let str = "The quick BroWn fOX jumpS Over tHe lazY DOg"
let nonUpperCase = NSCharacterSet.uppercaseLetterCharacterSet().invertedSet
let letters = str.componentsSeparatedByCharactersInSet(nonUpperCase)
"".join(letters) // "TBWOXSOHYDO"

Upvotes: 5

Joachim Isaksson
Joachim Isaksson

Reputation: 180867

You could always see if the lowercase representation is different from the current value;

let string = "The quick BroWn fOX jumpS Over tHe lazY DOg"
var output = ""

for chr in string {
    var str = String(chr)
    if str.lowercaseString != str {
        output += str
    }
}
print(output)

>>> TBWOXSOHYDO

Upvotes: 20

Related Questions