Reputation: 3009
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
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
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
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
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
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
Reputation: 5842
Simple Swifty extension :
extension String {
var isLower: Bool {
return String(self.filter { String($0) == String($0).lowercased() }) == self
}
}
Upvotes: 0
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
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
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
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
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.")
}
}
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
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
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
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
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
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
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
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