Entfernen Sie alle nicht numerischen Zeichen schnell aus einer Zeichenfolge

84

Ich muss einige unbekannte Daten analysieren, die nur ein numerischer Wert sein sollten, aber möglicherweise Leerzeichen oder andere nicht alphanumerische Zeichen enthalten.

Gibt es eine neue Möglichkeit, dies in Swift zu tun? Alles, was ich online finden kann, scheint die alte C-Methode zu sein.

Ich schaue auf stringByTrimmingCharactersInSet- da ich sicher bin, dass meine Eingaben nur Leerzeichen / Sonderzeichen am Anfang oder Ende der Zeichenfolge enthalten. Gibt es eingebaute Zeichensätze, die ich dafür verwenden kann? Oder muss ich meine eigenen erstellen?

Ich hatte gehofft, dass es so etwas geben stringFromCharactersInSet()würde, mit dem ich nur gültige Zeichen angeben könnte, die ich behalten möchte

Dan
quelle

Antworten:

183

Ich hatte gehofft, dass es so etwas wie stringFromCharactersInSet () geben würde, mit dem ich nur gültige Zeichen angeben könnte, die beibehalten werden sollen.

Sie können entweder trimmingCharactersmit dem invertedZeichensatz Zeichen vom Anfang oder vom Ende der Zeichenfolge entfernen. In Swift 3 und höher:

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

Oder, wenn Sie wollen Zeichen nicht numerisch entfernen überall in der Zeichenfolge (nicht nur den Anfang oder das Ende), können Sie filterdas characters, zum Beispiel in Swift 4.2.1:

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

Wenn Sie Zeichen von einer beliebigen Stelle in der Zeichenfolge aus einem CharacterSet entfernen möchten, verwenden Sie:

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

Wenn Sie nur gültige Zeichenfolgen eines bestimmten Formats (z. B. ####.##) abgleichen möchten , können Sie auch reguläre Ausdrücke verwenden. Zum Beispiel:

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

Das Verhalten dieser verschiedenen Ansätze unterscheidet sich geringfügig, sodass es nur darauf ankommt, was Sie genau tun möchten. Schließen Sie den Dezimalpunkt ein oder aus, wenn Sie Dezimalzahlen oder nur Ganzzahlen möchten. Es gibt viele Möglichkeiten, dies zu erreichen.


Informationen zur älteren Swift 2-Syntax finden Sie in der vorherigen Version dieser Antwort .

rauben
quelle
Können Sie erklären, warum Sie invertedden Zeichensatz im Swift 3-Beispiel bearbeiten müssen?
Andy Ibanez
4
@AndyIbanez Es ist wie zu sagen, wenn "ABC" die Zeichen sind, die ich behalten möchte, dann schneide alles ab, was nicht "ABC" ist.
Scott McKenzie
1
In Swift 4.2.1 let result = String(string.characters.filter { "01234567890.".characters.contains($0) })kann auflet result = string.filter("01234567890.".contains)
Leo Dabus
41
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)

Sie können diese Antwort positiv bewerten .

Tom Howard
quelle
3
Vielen Dank! Nachdem ich alle Swift3-Änderungen erhalten hatte, blieb mir Folgendes übrig: myStr.replacingOccurrences (von: "[^ 0-9]", mit: "", Optionen: .regularExpression)
bobwki
29

Ich bevorzuge diese Lösung , weil ich Erweiterungen mag und sie mir etwas sauberer erscheint. Hier wiedergegebene Lösung:

extension String {
    var digits: String {
        return components(separatedBy: CharacterSet.decimalDigits.inverted)
            .joined()
    }
}
Jake Cronin
quelle
scheint Dezimalstellen zu
entfernen
18

Swift 4

Ich habe einen anständigen Weg gefunden , nur alphanumerische Zeichen aus einer Zeichenfolge zu erhalten. Zum Beispiel:-

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

}
Aashish
quelle
17

Sie können die UnicodeScalarView der Zeichenfolge mithilfe des Mustervergleichsoperators für Bereiche filtern, einen UnicodeScalar ClosedRange von 0 bis 9 übergeben und eine neue Zeichenfolge mit der resultierenden UnicodeScalarView initialisieren:

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

"abc12345".digits   // "12345"

bearbeiten / aktualisieren:

Swift 4.2

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

oder als mutierende Methode

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

Swift 5.2 • Xcode 11.4 oder höher

In Swift5 können wir eine neue Character-Eigenschaft namens verwenden isWholeNumber:

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

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

Um auch einen Punkt zuzulassen, können wir Character erweitern und eine berechnete Eigenschaft erstellen:

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

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

Spielplatztests:

"abc12345".digits   // "12345"

var str = "123abc0"
str.removeAllNonNumeric()
print(str) //"1230"

"Testing0123456789.".digitsAndPeriods // "0123456789."
Leo Dabus
quelle
Tolle Lösung für Swift 5! Wie kann ich "." oder "," innerhalb des Strings, um einen String in einen Double konvertieren zu können?
Hans Bondoka
1
@ HansBondoka Danke. Versuchen Sie es so filter { $0.isNumber || $0 == "." }.
Leo Dabus
11

Eine Lösung mit der filterFunktion undrangeOfCharacterFromSet

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µ

Um nur nach numerischen Zeichen zu filtern, verwenden Sie

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

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

oder

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
vadian
quelle
Ich möchte keine Alpha-Werte, obwohl ich keine erwarte
Dan
Bitte sei spezifischer. Die Überschrift sagt non-alphanumeric;-) Ich habe die Antwort für numerische Zeichen bearbeitet.
Vadian
8

Swift 4

Aber ohne Erweiterungen oder KomponentenSeparatedByCharactersInSet, die nicht so gut lesen.

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

Swift 3 filtert alle außer Zahlen

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

Swift 4.2

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

Sie können so etwas tun ...

let string = "[,myString1. \"" // string : [,myString1. " 
let characterSet = NSCharacterSet(charactersInString: "[,. \"")
let finalString = (string.componentsSeparatedByCharactersInSet(characterSet) as NSArray).componentsJoinedByString("") 
print(finalString)   
//finalString will be "myString1"
vivek takrani
quelle
Ich habe keine vollständige Vorstellung davon, welche Zeichen in der Zeichenfolge enthalten sein können - und ich möchte nur numerische Werte am Ende. Dies würde mich brauchen, um alle Charaktere aufzulisten, die ich nicht will. Es gibt viele Charaktere, die sein könnten
Dan
2

Das Problem bei Robs erster Lösung besteht darin, stringByTrimmingCharactersInSetnur die Enden der Zeichenfolge zu filtern und nicht durchgehend, wie in der Apple-Dokumentation angegeben:

Gibt eine neue Zeichenfolge zurück, die durch Entfernen der in einem bestimmten Zeichensatz enthaltenen Empfängerzeichen an beiden Enden erstellt wurde.

Verwenden Sie stattdessen, componentsSeparatedByCharactersInSetum zuerst alle Nichtvorkommen des Zeichensatzes in Arrays zu isolieren und sie anschließend mit einem leeren Zeichenfolgentrennzeichen zu verbinden:

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

Welches kehrt zurück 123456789

Ryan Brodie
quelle
Keine Notwendigkeit zu verwenden NSCharacterSet. Aber deine Antwort ist die beste. Hier ist eine allgemeine Version:extension String { func removingCharactersNot(in charSet: CharacterSet) -> String { return self.components(separatedBy: charSet.inverted).joined(separator: "") } }
Xaphod
2

Swift 3

extension String {
    var keepNumericsOnly: String {
        return self.components(separatedBy: CharacterSet(charactersIn: "0123456789").inverted).joined(separator: "")
    }
}
Ehab Saifan
quelle
2
let string = "+1*(234) fds567@-8/90-"
let onlyNumbers = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()

print(onlyNumbers) // "1234567890"

oder

extension String {

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

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

Swift 4.0 Version

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

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
Vishal Vaghasiya
quelle
Das Initialisieren einer neuen UnicodeScalarView ist sinnlos. Das Ergebnis des Filters ist bereits eine UnicodeScalarView. return String(passed)
Leo Dabus
1

Swift 4.2

let digitChars  = yourString.components(separatedBy:
        CharacterSet.decimalDigits.inverted).joined(separator: "")
Debaprio B.
quelle
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
    }
}
hhamm
quelle