快速从字符串中删除所有非数字字符

Posted

技术标签:

【中文标题】快速从字符串中删除所有非数字字符【英文标题】:Remove all non-numeric characters from a string in swift 【发布时间】:2016-04-13 09:28:27 【问题描述】:

我需要解析一些未知数据,这些数据应该只是一个数值,但可能包含空格或其他非字母数字字符。

在 Swift 中是否有一种新的方法可以做到这一点?我在网上能找到的似乎都是旧的 C 做事方式。

我正在查看stringByTrimmingCharactersInSet - 因为我确信我的输入只会在字符串的开头或结尾包含空格/特殊字符。有没有我可以使用的内置字符集?还是我需要自己创建?

我希望有类似stringFromCharactersInSet() 这样的东西,它允许我只指定要保留的有效字符

【问题讨论】:

【参考方案1】:

我希望有类似 stringFromCharactersInSet() 的东西,它允许我只指定要保留的有效字符。

您可以使用trimmingCharactersinverted 字符集来删除字符串开头或结尾的字符。在 Swift 3 及更高版本中:

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

或者,如果您想删除字符串中任何位置的非数字字符(不仅仅是开头或结尾),您可以filter characters,例如在 Swift 4.2.1 中:

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

或者,如果您想从字符串中的任何位置从 CharacterSet 中删除字符,请使用:

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

或者,如果您只想匹配某种格式的有效字符串(例如####.##),您可以使用正则表达式。例如:

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

这些不同方法的行为略有不同,因此它仅取决于您要执行的操作。如果您需要十进制数或仅整数,请包括或排除小数点。有很多方法可以做到这一点。


对于较旧的 Swift 2 语法,请参阅 previous revision of this answer。

【讨论】:

你能解释一下为什么你需要对 Swift 3 例子中的字符集做inverted 吗? @AndyIbanez 就像说,如果“ABC”是我想要保留的字符,那么修剪所有不是“ABC”的字符。 在 Swift 4.2.1 中 let result = String(string.characters.filter "01234567890.".characters.contains($0) ) 可以缩短为 let result = string.filter("01234567890.".contains)【参考方案2】:
let result = string.stringByReplacingOccurrencesOfString("[^0-9]", withString: "", options: NSStringCompareOptions.RegularExpressionSearch, range:nil).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())

斯威夫特 3

let result = string.replacingOccurrences( of:"[^0-9]", with: "", options: .regularExpression)

您可以投票给this answer。

【讨论】:

谢谢!在获得所有 Swift3 更改后,我得到了这个:myStr.replacingOccurrences(of:"[^0-9]", with: "", options: .regularExpression)【参考方案3】:

我更喜欢this solution,因为我喜欢扩展,而且它对我来说似乎更干净一些。此处转载解决方案:

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

【讨论】:

似乎去掉了小数【参考方案4】:

您可以使用范围的模式匹配运算符过滤字符串的 UnicodeScalarView,将 UnicodeScalar ClosedRange 从 0 传递到 9 并使用生成的 UnicodeScalarView 初始化新字符串:

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


"abc12345".digits   // "12345"

编辑/更新:

斯威夫特 4.2

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

或作为变异方法

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


Swift 5.2 • Xcode 11.4 或更高版本

在 Swift5 中,我们可以使用一个名为 isWholeNumber 的新 Character 属性:

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


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


为了也允许一个句点,我们可以扩展 Character 并创建一个计算属性:

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


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


游乐场测试:

"abc12345".digits   // "12345"

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

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

【讨论】:

Swift 5 的绝佳解决方案!我怎么能离开“。”或字符串中的“,”,以便能够将字符串转换为双精度数?【参考方案5】:

Swift 4

我找到了一种体面的方法来从字符串中只获取字母数字字符集。 例如:-

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


【讨论】:

【参考方案6】:

使用filter 函数和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µ

要仅过滤数字字符,请使用

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

let numericSet = "0123456789"
let filteredCharacters = string.characters.filter 
  return numericSet.containsString(String($0))

let filteredString = String(filteredCharacters) // -> 347

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

【讨论】:

我不想要任何 alpha 值,虽然我不希望有任何 请更具体。标题写着non-alphanumeric ;-) 我编辑了数字字符的答案。【参考方案7】:

斯威夫特 4

但如果没有扩展或 componentsSeparatedByCharactersInSet 也无法读取。

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

【讨论】:

【参考方案8】:

Swift 3,过滤除数字以外的所有内容

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

【讨论】:

【参考方案9】:

斯威夫特 4.2

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

【讨论】:

【参考方案10】:
let string = "+1*(234) fds567@-8/90-"
let onlyNumbers = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()

print(onlyNumbers) // "1234567890"

extension String 

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


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

【讨论】:

【参考方案11】:

你可以做这样的事情......

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

【讨论】:

我不完全了解字符串中可能包含哪些字符 - 我只想要最后的数字值。这需要我列出所有我不想要的字符.. 有很多字符可能是【参考方案12】:

Rob 的第一个解决方案的问题是 stringByTrimmingCharactersInSet 仅过滤字符串的结尾而不是整个字符串,如 Apple 文档中所述:

返回一个新字符串,该字符串通过从给定字符集中包含的接收者字符的两端删除。

改为使用componentsSeparatedByCharactersInSet,首先将所有未出现的字符集隔离到数组中,然后用空字符串分隔符将它们连接起来:

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

返回123456789

【讨论】:

无需使用NSCharacterSet。但你的答案是最好的。这是一个通用版本:extension String func removingCharactersNot(in charSet: CharacterSet) -> String return self.components(separatedBy: charSet.inverted).joined(separator: "") 【参考方案13】:

斯威夫特 3

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

【讨论】:

【参考方案14】:

Swift 4.0 版本

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

【讨论】:

【参考方案15】:

斯威夫特 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

【讨论】:

初始化一个新的 UnicodeScalarView 是没有意义的。过滤器的结果它已经是一个 UnicodeScalarView。 return String(passed)【参考方案16】:

斯威夫特 4.2

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

【讨论】:

【参考方案17】:

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
    

【讨论】:

以上是关于快速从字符串中删除所有非数字字符的主要内容,如果未能解决你的问题,请参考以下文章

从 lua 字符串中删除所有非字母数字字符

从Python中的字符串中删除所有非数字字符

从字符串中删除非数字字符(不包括句点和逗号)(即删除除数字、逗号和句点之外的所有字符)

从字符串 Typescript 中删除非英语 [重复]

从字符串中删除非字母数字字符(包括 ß、Ê 等)

如何从 Python 的数据框列中的字符串中删除非字母数字字符?