Tengo la necesidad de analizar algunos datos desconocidos que deberían ser solo un valor numérico, pero pueden contener espacios en blanco u otros caracteres no alfanuméricos.
¿Existe una nueva forma de hacer esto en Swift? Todo lo que puedo encontrar en línea parece ser la antigua forma de C de hacer las cosas.
Estoy mirando stringByTrimmingCharactersInSet
, ya que estoy seguro de que mis entradas solo tendrán espacios en blanco / caracteres especiales al principio o al final de la cadena. ¿Hay algún conjunto de caracteres incorporado que pueda usar para esto? ¿O necesito crear el mío propio?
Esperaba que hubiera algo así como stringFromCharactersInSet()
que me permitiera especificar solo caracteres válidos para mantener
inverted
en el juego de caracteres en el ejemplo de Swift 3?let result = String(string.characters.filter { "01234567890.".characters.contains($0) })
se puede acortar alet result = string.filter("01234567890.".contains)
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)
Puedes votar esta respuesta .
fuente
Prefiero esta solución , porque me gustan las extensiones, y me parece un poco más limpia. Solución reproducida aquí:
extension String { var digits: String { return components(separatedBy: CharacterSet.decimalDigits.inverted) .joined() } }
fuente
Encontré una forma decente de obtener solo caracteres alfanuméricos configurados a partir de una cadena. Por ejemplo:-
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 }
fuente
Puede filtrar el UnicodeScalarView de la cadena utilizando el operador de coincidencia de patrones para rangos, pasar un UnicodeScalar ClosedRange de 0 a 9 e inicializar una nueva Cadena con el UnicodeScalarView resultante:
extension String { private static var digits = UnicodeScalar("0")..."9" var digits: String { return String(unicodeScalars.filter(String.digits.contains)) } } "abc12345".digits // "12345"
editar / actualizar:
Rápido 4.2
extension RangeReplaceableCollection where Self: StringProtocol { var digits: Self { return filter(("0"..."9").contains) } }
o como método mutante
extension RangeReplaceableCollection where Self: StringProtocol { mutating func removeAllNonNumeric() { removeAll { !("0"..."9" ~= $0) } } }
Swift 5.2 • Xcode 11.4 o posterior
En Swift5 podemos usar una nueva propiedad de carácter llamada
isWholeNumber
:extension RangeReplaceableCollection where Self: StringProtocol { var digits: Self { filter(\.isWholeNumber) } }
extension RangeReplaceableCollection where Self: StringProtocol { mutating func removeAllNonNumeric() { removeAll { !$0.isWholeNumber } } }
Para permitir un período también, podemos extender Character y crear una propiedad calculada:
extension Character { var isDecimalOrPeriod: Bool { "0"..."9" ~= self || self == "." } }
extension RangeReplaceableCollection where Self: StringProtocol { var digitsAndPeriods: Self { filter(\.isDecimalOrPeriod) } }
Prueba de patio de recreo:
"abc12345".digits // "12345" var str = "123abc0" str.removeAllNonNumeric() print(str) //"1230" "Testing0123456789.".digitsAndPeriods // "0123456789."
fuente
filter { $0.isNumber || $0 == "." }
. Prueba así .Una solución que usa la
filter
función yrangeOfCharacterFromSet
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µ
Para filtrar solo por caracteres numéricos, use
let string = "sld [f]34é7*˜µ" let numericSet = "0123456789" let filteredCharacters = string.characters.filter { return numericSet.containsString(String($0)) } let filteredString = String(filteredCharacters) // -> 347
o
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
fuente
non-alphanumeric
;-) Edité la respuesta para caracteres numéricos.Rápido 4
Pero sin extensiones o componentesSeparatedByCharactersInSet que no lee tan bien.
let allowedCharSet = NSCharacterSet.letters.union(.whitespaces) let filteredText = String(sourceText.unicodeScalars.filter(allowedCharSet.contains))
fuente
Swift 3, filtra todos excepto los números
let myString = "dasdf3453453fsdf23455sf.2234" let result = String(myString.characters.filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil }) print(result)
fuente
Rápido 4.2
let numericString = string.filter { (char) -> Bool in return char.isNumber }
fuente
Puedes hacer algo como esto ...
let string = "[,myString1. \"" // string : [,myString1. " let characterSet = NSCharacterSet(charactersInString: "[,. \"") let finalString = (string.componentsSeparatedByCharactersInSet(characterSet) as NSArray).componentsJoinedByString("") print(finalString) //finalString will be "myString1"
fuente
El problema con la primera solución de Rob es que
stringByTrimmingCharactersInSet
solo filtra los extremos de la cadena en lugar de todo, como se indica en la documentación de Apple:En su lugar, utilice
componentsSeparatedByCharactersInSet
para aislar primero todas las no ocurrencias del juego de caracteres en matrices y luego únalas con un separador de cadena vacío:"$$1234%^56()78*9££".componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "0123456789").invertedSet)).joinWithSeparator("")
Que vuelve
123456789
fuente
NSCharacterSet
. Pero tu respuesta es la mejor. Aquí hay una versión en general:extension String { func removingCharactersNot(in charSet: CharacterSet) -> String { return self.components(separatedBy: charSet.inverted).joined(separator: "") } }
Swift 3
extension String { var keepNumericsOnly: String { return self.components(separatedBy: CharacterSet(charactersIn: "0123456789").inverted).joined(separator: "") } }
fuente
let string = "+1*(234) fds567@-8/90-" let onlyNumbers = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined() print(onlyNumbers) // "1234567890"
o
extension String { func removeNonNumeric() -> String { return self.components(separatedBy: CharacterSet.decimalDigits.inverted).joined() } } let onlyNumbers = "+1*(234) fds567@-8/90-".removeNonNumeric() print(onlyNumbers)// "1234567890"
fuente
Versión Swift 4.0
extension String { var numbers: String { return String(describing: filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil }) } }
fuente
Rápido 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
fuente
return String(passed)
Rápido 4.2
let digitChars = yourString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
fuente
Versión Swift 3
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 } }
fuente