Как узнать, является ли буква буквенно-цифровой или цифрой в Swift

Я хочу подсчитать количество букв, цифр и специальных символов в следующей строке:

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

Я попытался:

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

но я получаю ошибки. Я пробовал всевозможные другие варианты этого - все еще получаю ошибку - например:

не удалось найти перегрузку для '‹=', которая принимает предоставленные аргументы


person sirab333    schedule 01.07.2014    source источник


Ответы (5)


Для Swift 5 см. ответ rustylepord.

Обновление для 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
    }
}

(Предыдущий ответ для более старых версий Swift)

Возможное решение Swift:

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++
    }
}

Обновление: приведенное выше решение работает только с символами в наборе символов ASCII, т. е. оно не распознает Ä, é или ø как буквы. В следующем альтернативном решении используется NSCharacterSet из платформы Foundation, которая может тестировать символы на основе их классов символов Unicode:

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++
    }
}

Обновление 2: Начиная с Xcode 6 beta 4, первое решение больше не работает, поскольку isAlpha() и связанные с ним (только для ASCII) методы были удалены из Swift. Второе решение все еще работает.

person Martin R    schedule 01.07.2014
comment
да, это прекрасно - как, черт возьми, вы узнали об isAlpha и isDigit????? :-) Я даже не знал, что такие существуют. (Серьезно - вы искали их или уже сталкивались с ними в предыдущих путешествиях?) - person sirab333; 01.07.2014
comment
@sirab333: isalpha() и друзья хорошо известны в C, см., например. developer.apple.com/library/ios/documentation/System/Conceptual/. Так что мне нужно было только выяснить, как их использовать из Swift. - Но обратите внимание, что это работает только для символов ASCII. Он не распознает буквы иностранных языков, такие как ä, è или ø. - person Martin R; 01.07.2014
comment
и он распознает + и - как цифру - person Christian Dietrich; 01.07.2014
comment
Интересный. У меня никогда не было ни C, ни C#, ни C++, ни любого другого C — я сразу же погрузился в Objective-C и никогда не оглядывался назад. В общем, вы бы сказали, что это законное решение - или есть более чистый способ сделать это только для Swift, без участия C? - person sirab333; 01.07.2014
comment
@ChristianDietrich: Вы уверены? Мой тест этого не подтверждает. - person Martin R; 01.07.2014
comment
@sirab333: isAlpha() является функцией Swift (имя которой совпадает с именем соответствующего макроса C). - Ничего другого в родном Swift не нашел. Но NSCharacterSet из фреймворков Foundation, вероятно, лучший инструмент. Я обновил ответ примером. - person Martin R; 01.07.2014
comment
@MartinR нет, я перепутал это со String(+).toInt(), который на самом деле делает это - person Christian Dietrich; 02.07.2014
comment
isAlpha и isDigit не являются методами UnicodeScalar - person Gerry; 19.09.2014
comment
@Gerry: Да, это то, что я добавил в качестве обновления 2: к моему ответу. - person Martin R; 19.09.2014
comment
@Warpzit: Да, в Swift 3 многое изменилось. Я обновил ответ, спасибо за отзыв. - person Martin R; 31.10.2016

Используйте значения unicodeScalars

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)
person Yao    schedule 15.10.2014

Для Swift 5 вы можете сделать следующее для простых строк, но будьте бдительны при обработке таких символов, как «1️⃣», «④», они также будут рассматриваться как числа.

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

var numberOfDigits = 0;
var numberOfLetters = 0;
var numberOfSymbols = 0;

phrase.forEach {

    if ($0.isNumber) {
        numberOfDigits += 1;
    }
    else if ($0.isLetter)  {
        numberOfLetters += 1
    }
    else if ($0.isSymbol || $0.isPunctuation || $0.isCurrencySymbol || $0.isMathSymbol) {
        numberOfSymbols += 1;
    }
}

print(#"\#(numberOfDigits)  || \#(numberOfLetters) || \#(numberOfSymbols)"#);
person rustylepord    schedule 06.09.2019

Я создал короткое расширение для подсчета букв и цифр для 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
  }
}

или функцию для подсчета любых CharacterSet, которые вы ввели

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

использование:

let phrase = "the final score is 23-13!"
let letterCount = phrase.characterCount(for: .letters)
person Rick Pasveer    schedule 11.04.2018

Если вам нужна только одна информация (буква, цифра или знак), вы можете сделать это в одной строке:

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

let count = phrase.filter{ $0.isLetter }.count
print(count) // "16\n"

Но выполнение phrase.filter несколько раз неэффективно, потому что оно перебирает всю строку.

person Alexander Langer    schedule 20.04.2021