Xóa tất cả các ký tự không phải số khỏi chuỗi nhanh chóng


84

Tôi có nhu cầu phân tích cú pháp một số dữ liệu không xác định chỉ nên là một giá trị số, nhưng có thể chứa khoảng trắng hoặc các ký tự không phải chữ và số khác.

Có cách nào mới để làm điều này trong Swift không? Tất cả những gì tôi có thể tìm thấy trên mạng dường như là cách làm cũ của C.

Tôi đang xem xét stringByTrimmingCharactersInSet- vì tôi chắc chắn rằng đầu vào của tôi sẽ chỉ có khoảng trắng / ký tự đặc biệt ở đầu hoặc cuối chuỗi. Có bất kỳ bộ ký tự tích hợp nào mà tôi có thể sử dụng cho việc này không? Hay tôi cần tạo của riêng tôi?

Tôi đã hy vọng sẽ có thứ gì đó giống như stringFromCharactersInSet()vậy sẽ cho phép tôi chỉ định các ký tự hợp lệ để giữ lại

Câu trả lời:


183

Tôi đã hy vọng sẽ có một cái gì đó giống như stringFromCharactersInSet () sẽ cho phép tôi chỉ định các ký tự hợp lệ để giữ lại.

Bạn có thể sử dụng trimmingCharactersvới bộ invertedký tự để xóa các ký tự khỏi đầu hoặc cuối chuỗi. Trong Swift 3 trở lên:

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

Hoặc, nếu bạn muốn xóa các ký tự không phải số ở bất kỳ đâu trong chuỗi (không chỉ phần đầu hoặc phần cuối), bạn có thể thực filterhiện characters, ví dụ như trong Swift 4.2.1:

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

Hoặc, nếu bạn muốn xóa các ký tự khỏi Tập ký tự khỏi bất kỳ vị trí nào trong chuỗi, hãy sử dụng:

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

Hoặc, nếu bạn chỉ muốn so khớp các chuỗi hợp lệ của một định dạng nhất định (ví dụ ####.##:), bạn có thể sử dụng biểu thức chính quy. Ví dụ:

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

Hành vi của các cách tiếp cận khác nhau này hơi khác nhau nên nó chỉ phụ thuộc vào chính xác những gì bạn đang cố gắng thực hiện. Bao gồm hoặc loại trừ dấu thập phân nếu bạn muốn số thập phân hoặc chỉ số nguyên. Có rất nhiều cách để thực hiện điều này.


Đối với cú pháp Swift 2 cũ hơn, hãy xem bản sửa đổi trước của câu trả lời này .


Bạn có thể giải thích tại sao bạn cần thực hiện invertedtrên bộ ký tự trong ví dụ Swift 3 không?
Andy Ibanez

4
@AndyIbanez Nó giống như nói rằng, nếu "ABC" là những ký tự tôi muốn giữ lại thì hãy cắt bỏ mọi thứ không phải là "ABC".
Scott McKenzie

1
Trong Swift 4.2.1 let result = String(string.characters.filter { "01234567890.".characters.contains($0) })có thể được rút ngắn thànhlet result = string.filter("01234567890.".contains)
Leo Dabus 13/02/19

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)

Bạn có thể tán thành câu trả lời này .


3
Cảm ơn! sau khi nhận được tất cả các Swift3 thay đổi, tôi bị bỏ lại với điều này: myStr.replacingOccurrences (của: "[^ 0-9]", với: "", lựa chọn: .regularExpression)
bobwki

29

Tôi thích giải pháp này hơn , vì tôi thích các tiện ích mở rộng và nó có vẻ gọn gàng hơn một chút đối với tôi. Giải pháp được sao chép ở đây:

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

dường như tách các số thập phân
markturnip

18

Swift 4

Tôi đã tìm thấy một cách hợp lý để chỉ lấy các ký tự số chữ cái được đặt từ một chuỗi. Ví dụ:-

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

}

17

Bạn có thể lọc UnicodeScalarView của chuỗi bằng cách sử dụng toán tử so khớp mẫu cho các phạm vi, chuyển một UnicodeScalar ClosedRange từ 0 đến 9 và khởi tạo một Chuỗi mới với UnicodeScalarView kết quả:

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

"abc12345".digits   // "12345"

chỉnh sửa / cập nhật:

Swift 4.2

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

hoặc như một phương pháp đột biến

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

Swift 5.2 • Xcode 11.4 trở lên

Trong Swift5, chúng ta có thể sử dụng một thuộc tính Character mới được gọi là isWholeNumber:

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

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

Để cho phép một khoảng thời gian, chúng tôi cũng có thể mở rộng Ký tự và tạo một thuộc tính được tính toán:

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

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

Thử nghiệm sân chơi:

"abc12345".digits   // "12345"

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

"Testing0123456789.".digitsAndPeriods // "0123456789."

Giải pháp tuyệt vời cho Swift 5! Làm sao tôi có thể rời khỏi đây "." hoặc "," trong Chuỗi, để có thể chuyển đổi Chuỗi thành Đôi?
Hans Bondoka

1
@HansBondoka Cảm ơn. Hãy thử như thế này filter { $0.isNumber || $0 == "." }.
Leo Dabus

11

Một giải pháp sử dụng filterchức năng và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µ

Để lọc chỉ các ký tự số, hãy sử dụng

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

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

hoặc là

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

Tôi không muốn bất kỳ giá trị alpha nào, mặc dù tôi không mong đợi bất kỳ giá trị nào
Dan

Vui lòng nói cụ thể hơn. Dòng tiêu đề cho biết non-alphanumeric;-) Tôi đã chỉnh sửa câu trả lời cho các ký tự số.
vadian

8

Swift 4

Nhưng nếu không có phần mở rộng hoặc thành phầnSeparatedByCharactersInSet thì nó cũng không đọc được.

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

4

Swift 3, lọc tất cả ngoại trừ số

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

3

Swift 4.2

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

2

Bạn có thể làm điều gì đó như thế này ...

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

Tôi không có ý tưởng đầy đủ về những ký tự nào có thể có trong chuỗi - và tôi chỉ muốn các giá trị số ở cuối. Điều này sẽ cần tôi vào danh sách tất cả các nhân vật tôi không muốn .. có rất nhiều các ký tự mà có thể là
Dan

2

Vấn đề với giải pháp đầu tiên của Rob là stringByTrimmingCharactersInSetchỉ lọc các đầu của chuỗi thay vì xuyên suốt, như đã nêu trong tài liệu của Apple:

Trả về một chuỗi mới được tạo bằng cách xóa từ cả hai đầu của các ký tự nhận có trong một tập ký tự nhất định.

Thay vào đó, sử dụng componentsSeparatedByCharactersInSetđầu tiên để tách tất cả các lần không xuất hiện của bộ ký tự thành các mảng và sau đó nối chúng bằng dấu phân tách chuỗi trống:

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

Cái nào trả về 123456789


Không cần sử dụng NSCharacterSet. Nhưng câu trả lời của bạn là tốt nhất. Đây là phiên bản chung: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: "")
    }
}

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

print(onlyNumbers) // "1234567890"

hoặc là

extension String {

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

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

1

Phiên bản Swift 4.0

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

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

Khởi tạo một UnicodeScalarView mới là vô nghĩa. Kết quả của bộ lọc nó đã là một UnicodeScalarView. return String(passed)
Leo Dabus

1

Swift 4.2

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

0

Phiên bả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
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.