Cómo saber si la letra es alfanumérica o dígito en Swift


Quiero contar el número de letras, dígitos y caracteres especiales en la siguiente cadena:

let phrase = "The final score was 32-31!"

Lo intenté:

for tempChar in phrase {
    if (tempChar >= "a" && tempChar <= "z") {
       letterCounter++
    }
// etc.

Pero estoy recibiendo errores. Probé todo tipo de otras variaciones sobre esto - aún obteniendo error-tales como:

No se pudo encontrar una sobrecarga para '

Author: Cœur, 2014-07-01

3 answers

Actualización para Swift 3:

let letters = CharacterSet.letters
let digits = CharacterSet.decimalDigits

var letterCount = 0
var digitCount = 0

for uni in phrase.unicodeScalars {
    if letters.contains(uni) {
        letterCount += 1
    } else if digits.contains(uni) {
        digitCount += 1
    }
}

(Respuesta anterior para versiones anteriores de Swift)

Una posible solución rápida:

var letterCounter = 0
var digitCount = 0
let phrase = "The final score was 32-31!"
for tempChar in phrase.unicodeScalars {
    if tempChar.isAlpha() {
        letterCounter++
    } else if tempChar.isDigit() {
        digitCount++
    }
}

Actualización: La solución anterior solo funciona con caracteres en el conjunto de caracteres ASCII, es decir, no reconoce Ä, é o ø como letras. La siguiente alternativa la solución utiliza NSCharacterSet del framework Foundation, que puede probar caracteres basado en su carácter Unicode clases:

let letters = NSCharacterSet.letterCharacterSet()
let digits = NSCharacterSet.decimalDigitCharacterSet()

var letterCount = 0
var digitCount = 0

for uni in phrase.unicodeScalars {
    if letters.longCharacterIsMember(uni.value) {
        letterCount++
    } else if digits.longCharacterIsMember(uni.value) {
        digitCount++
    }
}

Actualización 2: A partir de Xcode 6 beta 4, la primera solución ya no funciona, porque los métodos isAlpha() y relacionados (solo ASCII) han sido eliminados de Swift. La segunda solución todavía funciona.

 50
Author: Martin R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-19 06:57:05

Utilice los valores de unicodescalares

let phrase = "The final score was 32-31!"
var letterCounter = 0, digitCounter = 0
for scalar in phrase.unicodeScalars {
    let value = scalar.value
    if (value >= 65 && value <= 90) || (value >= 97 && value <= 122) {++letterCounter}
    if (value >= 48 && value <= 57) {++digitCounter}
}
println(letterCounter)
println(digitCounter)
 4
Author: Yao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-08 08:29:42

He creado una extensión corta para el recuento de letras y dígitos para un String

extension String {
  var letterCount : Int {
    return self.unicodeScalars.filter({ CharacterSet.letters.contains($0) }).count
  }

  var digitCount : Int {
   return self.unicodeScalars.filter({ CharacterSet.decimalDigits.contains($0) }).count
  }
}

O una función para obtener un conteo para cualquier CharacterSet que pongas en

extension String {    
  func characterCount(for set: CharacterSet) -> Int {
    return self.unicodeScalars.filter({ set.contains($0) }).count
  }
}

Uso:

let phrase = "the final score is 23-13!"
let letterCount = phrase.characterCount(for: .letters)
 0
Author: Rick Pasveer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-11 10:10:13