Verwijder alle niet-numerieke tekens uit een string in swift

Ik heb de behoefte om onbekende gegevens te ontleden die alleen een numerieke waarde zouden moeten zijn, maar die spaties of andere niet-alfanumerieke tekens kunnen bevatten.

Is er een nieuwe manier om dit in Swift te doen? Alles wat ik online kan vinden, lijkt de oude C-manier om dingen te doen.

Ik kijk naar stringByTrimmingCharactersInSet– omdat ik zeker weet dat mijn invoer alleen spaties/speciale tekens aan het begin of einde van de tekenreeks zal hebben. Zijn er ingebouwde tekensets die ik hiervoor kan gebruiken? Of moet ik er zelf een maken?

Ik hoopte dat er zoiets zou zijn als stringFromCharactersInSet()waarmee ik alleen geldige tekens zou kunnen opgeven om te behouden


Antwoord 1, autoriteit 100%

Ik hoopte dat er zoiets zou zijn als stringFromCharactersInSet() waarmee ik alleen geldige tekens zou kunnen opgeven om te bewaren.

Je kunt ofwel trimmingCharactersgebruiken met de invertedtekenset om tekens aan het begin of het einde van de tekenreeks te verwijderen. In Swift 3 en hoger:

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

Of, als u niet-numerieke tekens ergens in de tekenreeks wilt verwijderen (niet alleen het begin of einde), kunt u filterde characters, b.v. in Swift 4.2.1:

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

Of, als u tekens uit een CharacterSet wilt verwijderen van waar dan ook in de string, gebruik:

let result = String(string.unicodeScalars.filter(CharacterSet.whitespaces.inverted.contains))

Of, als je alleen geldige tekenreeksen van een bepaald formaat wilt matchen (bijv. ####.##), kun je reguliere expressie gebruiken. Bijvoorbeeld:

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

Het gedrag van deze verschillende benaderingen verschilt enigszins, dus het hangt er gewoon van af wat je precies probeert te doen. Voeg de komma toe of sluit deze uit als u decimale getallen wilt, of alleen gehele getallen. Er zijn veel manieren om dit te bereiken.


Voor oudere Swift 2-syntaxis, zie vorige revisie van dit antwoord.


Antwoord 2, autoriteit 21%

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)

Je kunt dit antwoordupvoten.


Antwoord 3, autoriteit 15%

Ik geef de voorkeur aan deze oplossing, omdat ik van extensies houd, en het lijkt me wat schoner. Oplossing hier weergegeven:

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

Antwoord 4, autoriteit 10%

Je kunt de UnicodeScalarView van de string filteren met behulp van de patroonvergelijkingsoperator voor bereiken, een UnicodeScalar ClosedRange van 0 tot 9 doorgeven en een nieuwe String initialiseren met de resulterende UnicodeScalarView:

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

bewerken/bijwerken:

Swift 4.2

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

of als een mutatiemethode

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

Swift 5.2 • Xcode 11.4 of hoger

In Swift5 kunnen we een nieuwe karaktereigenschap gebruiken met de naam isWholeNumber:

extension RangeReplaceableCollection where Self: StringProtocol {
    var digits: Self { filter(\.isWholeNumber) }
}

extension RangeReplaceableCollection where Self: StringProtocol {
    mutating func removeAllNonNumeric() {
        removeAll { !$0.isWholeNumber }
    }
}

Om ook een punt toe te staan, kunnen we Character uitbreiden en een berekende eigenschap maken:

extension Character {
    var isDecimalOrPeriod: Bool { "0"..."9" ~= self || self == "." }
}

extension RangeReplaceableCollection where Self: StringProtocol {
    var digitsAndPeriods: Self { filter(\.isDecimalOrPeriod) }
}

Speeltuin testen:

"abc12345".digits   // "12345"
var str = "123abc0"
str.removeAllNonNumeric()
print(str) //"1230"
"Testing0123456789.".digitsAndPeriods // "0123456789."

Antwoord 5, autoriteit 8%

Swift 4

Ik heb een fatsoenlijke manier gevonden om alleen alfanumerieketekens uit een string te halen.
Bijvoorbeeld:-

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
}

Antwoord 6, autoriteit 5%

Een oplossing die de functie filteren rangeOfCharacterFromSet

gebruikt

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µ

Gebruik om te filteren op alleen numerieke tekens

let string = "sld [f]34é7*˜µ"
let numericSet = "0123456789"
let filteredCharacters = string.characters.filter {
  return numericSet.containsString(String($0))
}
let filteredString = String(filteredCharacters) // -> 347

of

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

Antwoord 7, autoriteit 4%

Swift 4

Maar zonder extensies of componentenSeparatedByCharactersInSet die niet zo goed leest.

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

Antwoord 8, autoriteit 2%

Swift 3, filtert alles behalve nummers

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

Antwoord 9, autoriteit 2%

Swift 4.2

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

Antwoord 10

let string = "+1*(234) fds567@-8/90-"
let onlyNumbers = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
print(onlyNumbers) // "1234567890"

of

extension String {
  func removeNonNumeric() -> String {
    return self.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
  }
}
let onlyNumbers = "+1*(234) fds567@-8/90-".removeNonNumeric() 
print(onlyNumbers)// "1234567890"

Antwoord 11

Je kunt zoiets als dit doen…

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

Antwoord 12

Het probleem met Rob’s eerste oplossing is dat stringByTrimmingCharactersInSetalleen de uiteinden van de string filtert in plaats van overal, zoals vermeld in de documentatie van Apple:

Retourneert een nieuwe tekenreeks die is gemaakt door aan beide uiteinden van de ontvangende tekens in een bepaalde tekenset te verwijderen.

Gebruik in plaats daarvan componentsSeparatedByCharactersInSetom eerst alle niet-voorvallen van de tekenset te isoleren in arrays en ze vervolgens samen te voegen met een leeg tekenreeksscheidingsteken:

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

Wat resulteert in 123456789


Antwoord 13

Swift 3

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

Antwoord 14

Swift 4.0-versie

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

Antwoord 15

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

Antwoord 16

Swift 4.2

let digitChars  = yourString.components(separatedBy:
        CharacterSet.decimalDigits.inverted).joined(separator: "")

Antwoord 17

Swift 3-versie

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

Other episodes