web-dev-qa-db-fra.com

Supprimer tous les caractères non numériques d'une chaîne en swift

J'ai le besoin d'analyser des données inconnues qui devraient juste être une valeur numérique, mais peuvent contenir des espaces ou d'autres caractères non alphanumériques.

Y a-t-il une nouvelle façon de faire cela à Swift? Tout ce que je peux trouver en ligne semble être l’ancienne façon de faire les choses. 

Je regarde stringByTrimmingCharactersInSet - car je suis sûr que mes entrées n'auront que des espaces/des caractères spéciaux au début ou à la fin de la chaîne. Existe-t-il des jeux de caractères intégrés que je peux utiliser pour cela? Ou dois-je créer le mien?

J'espérais qu'il y aurait quelque chose comme stringFromCharactersInSet() qui me permettrait d'indiquer uniquement les caractères valides à conserver.

51
Dan

J'espérais qu'il y aurait quelque chose comme stringFromCharactersInSet () qui me permettrait de spécifier uniquement les caractères valides à conserver.

Vous pouvez utiliser trimmingCharacters avec le jeu de caractères inverted pour supprimer les caractères du début ou de la fin de la chaîne. Dans Swift 3 et plus tard:

let result = string.trimmingCharacters(in: CharacterSet(charactersIn: "01234567890.").inverted)

Ou, si vous souhaitez supprimer des caractères non numériques n'importe où dans la chaîne (pas seulement le début ou la fin), vous pouvez filter la characters, par exemple dans Swift 4.2.1:

let result = string.filter("01234567890.".contains)

Ou, si vous souhaitez uniquement faire correspondre des chaînes valides d'un certain format (par exemple, ####.##), vous pouvez utiliser une expression régulière. Par exemple:

if let range = string.range(of: "\\d+(\\.\\d*)?", options: .regularExpression) {
    let result = string[range] // or `String(string[range])` if you need `String`
}

Le comportement de ces différentes approches est légèrement différent, cela dépend donc de ce que vous essayez de faire. Incluez ou excluez le point décimal si vous voulez des nombres décimaux, ou seulement des entiers. Il y a beaucoup de façons d'accomplir cela.


Pour l'ancienne syntaxe Swift 2, voir révision précédente de cette réponse .

96
Rob
let result = string.stringByReplacingOccurrencesOfString("[^0-9]", withString: "", options: NSStringCompareOptions.RegularExpressionSearch, range:nil).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())

Swift 3

let result = string.replacingOccurrences( of:"[^0-9]", with: "", options: .regularExpression)

Vous pouvez upvote cette réponse

29
Tom Howard

Je préfère cette solution , parce que j'aime les extensions et qu'elle me semble un peu plus propre. Solution reproduite ici:

extension String {
    var digits: String {
        return components(separatedBy: CharacterSet.decimalDigits.inverted)
            .joined()
    }
}
20
Jake Cronin

Swift 4

J'ai trouvé un moyen décent de obtenir uniquement alphanumérique caractères définis depuis une chaîne. Par exemple:-

func getAlphaNumericValue() {

    var yourString  = "123456789!@#$%^&*()AnyThingYouWant"

    let unsafeChars = CharacterSet.alphanumerics.inverted  // Remove the .inverted to get the opposite result.  

    let cleanChars  = yourString.components(separatedBy: unsafeChars).joined(separator: "")


    print(cleanChars)  // 123456789AnyThingYouWant

}
11
Aashish

Une solution utilisant la fonction filter et rangeOfCharacterFromSet

let string = "sld [f]34é7*˜µ"

let alphaNumericCharacterSet = NSCharacterSet.alphanumericCharacterSet()
let filteredCharacters = string.characters.filter {
  return  String($0).rangeOfCharacterFromSet(alphaNumericCharacterSet) != nil
}
let filteredString = String(filteredCharacters) // -> sldf34é7µ

Pour filtrer uniquement les caractères numériques, utilisez

let string = "sld [f]34é7*˜µ"

let numericSet = "0123456789"
let filteredCharacters = string.characters.filter {
  return numericSet.containsString(String($0))
}
let filteredString = String(filteredCharacters) // -> 347

ou

let numericSet : [Character] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
let filteredCharacters = string.characters.filter {
  return numericSet.contains($0)
}
let filteredString = String(filteredCharacters) // -> 347
10
vadian

Vous pouvez filtrer la vue UnicodeScalar de la chaîne à l'aide de l'opérateur de correspondance de modèle pour les plages, passer un UnicodeScalar ClosedRange de 0 à 9 et initialiser une nouvelle chaîne avec le résultat UnicodeScalarView:

extension String {
    private static var digits = UnicodeScalar("0")..."9"
    var digits: String {
        return String(unicodeScalars.filter(String.digits.contains))
    }
}

"abc12345".digits   // "12345"

éditer/mettre à jour:

Swift 4.2

extension RangeReplaceableCollection where Self: StringProtocol {
    var digits: Self {
        return filter(("0"..."9").contains)
    }
}

ou comme méthode de mutation

extension RangeReplaceableCollection where Self: StringProtocol {
    mutating func removeAllNonNumeric() {
        removeAll { !("0"..."9" ~= $0) }
    }
}
5
Leo Dabus

Swift 3, filtre tout sauf les nombres

let myString = "dasdf3453453fsdf23455sf.2234"
let result = String(myString.characters.filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil })
print(result)
4
CodeOverRide

Swift 4

Mais sans extensions ni composantsSeparatedByCharactersInSet qui ne lit pas aussi bien.

let allowedCharSet = NSCharacterSet.letters.union(.whitespaces)
let filteredText = String(sourceText.unicodeScalars.filter(allowedCharSet.contains))
3
Steve Moser

Vous pouvez faire quelque chose comme ça ...

let string = "[,myString1. \"" // string : [,myString1. " 
let characterSet = NSCharacterSet(charactersInString: "[,. \"")
let finalString = (string.componentsSeparatedByCharactersInSet(characterSet) as NSArray).componentsJoinedByString("") 
print(finalString)   
//finalString will be "myString1"
2
vivek takrani

Le problème avec la première solution de Rob est stringByTrimmingCharactersInSet ne filtre que les extrémités de la chaîne plutôt que de bout en bout, comme indiqué dans la documentation d'Apple:

Retourne une nouvelle chaîne créée en supprimant aux deux extrémités des caractères du récepteur contenus dans un jeu de caractères donné.

A la place, utilisez componentsSeparatedByCharactersInSet pour isoler d’abord toutes les non-occurrences du jeu de caractères dans des tableaux, puis les associer avec un séparateur de chaîne vide:

"$$1234%^56()78*9££".componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "0123456789").invertedSet)).joinWithSeparator("")

Ce qui retourne 123456789

2
Ryan Brodie

Swift 3

extension String {
    var keepNumericsOnly: String {
        return self.components(separatedBy: CharacterSet(charactersIn: "0123456789").inverted).joined(separator: "")
    }
}
2
Ehab Saifan

Swift 4.0 version

extension String {
    var numbers: String {
        return String(describing: filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil })
    }
}
1
rockdaswift

Swift 4

String.Swift

import Foundation

extension String {

    func removeCharacters(from forbiddenChars: CharacterSet) -> String {
        let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
        return String(String.UnicodeScalarView(passed))
    }

    func removeCharacters(from: String) -> String {
        return removeCharacters(from: CharacterSet(charactersIn: from))
    }
}

ViewController.Swift

let character = "1Vi234s56a78l9"
        let alphaNumericSet = character.removeCharacters(from: CharacterSet.decimalDigits.inverted)
        print(alphaNumericSet) // will print: 123456789

        let alphaNumericCharacterSet = character.removeCharacters(from: "0123456789")
        print("no digits",alphaNumericCharacterSet) // will print: Vishal
1
Vishal Vaghasiya

Swift 4.2

let numericString = string.filter { (char) -> Bool in
    return char.isNumber
}
0
mef27

Swift 4.2

let digitChars  = yourString.components(separatedBy:
        CharacterSet.decimalDigits.inverted).joined(separator: "")
0
Debaprio B
let string = "+1*(234) fds567@-8/90-"
let onlyNumbers = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()

print(onlyNumbers) // "1234567890"

ou

extension String {

  func removeNonNumeric() -> String {
    return self.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
  }
}

let onlyNumbers = "+1*(234) fds567@-8/90-".removeNonNumeric() 
print(onlyNumbers)// "1234567890"
0

Swift 3 Version

extension String
{
    func trimmingCharactersNot(in charSet: CharacterSet) -> String
    {
        var s:String = ""
        for unicodeScalar in self.unicodeScalars
        {
            if charSet.contains(unicodeScalar)
            {
                s.append(String(unicodeScalar))
            }
        }
        return s
    }
}
0
hhamm