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.
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 .
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 .
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()
}
}
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
}
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
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) }
}
}
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)
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))
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"
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
Swift 3
extension String {
var keepNumericsOnly: String {
return self.components(separatedBy: CharacterSet(charactersIn: "0123456789").inverted).joined(separator: "")
}
}
Swift 4.0 version
extension String {
var numbers: String {
return String(describing: filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil })
}
}
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
Swift 4.2
let numericString = string.filter { (char) -> Bool in
return char.isNumber
}
Swift 4.2
let digitChars = yourString.components(separatedBy:
CharacterSet.decimalDigits.inverted).joined(separator: "")
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"
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
}
}