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


80

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

Swift中是否有新的方法?我在网上可以找到的所有东西似乎都是旧的C方式。

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

我希望会有类似的东西stringFromCharactersInSet()允许我仅指定要保留的有效字符

Answers:


177

我希望会有像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语法,请参见此答案的先前版本


您能否解释一下为什么需要处理invertedSwift 3示例中的字符集?
安迪·伊瓦涅斯

4
@AndyIbanez这就像在说,如果我要保留“ ABC”字符,则剪裁所有非“ ABC”字符。
Scott McKenzie '18

1
在Swift 4.2.1let result = String(string.characters.filter { "01234567890.".characters.contains($0) })中可以缩短为let result = string.filter("01234567890.".contains)
Leo Dabus

40
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)

您可以赞成这个答案


3
谢谢!在获得所有Swift3更改之后,我得到的是:myStr.replacingOccurrences(of:“ [^ 0-9]”,with:“”,options:.regularExpression)
bobwki

29

我更喜欢这种解决方案,因为我喜欢扩展,对我来说似乎更干净。解决方案转载于此:

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

似乎要删除小数点
markturnip

17

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

}

17

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

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中,我们可以使用一个新的Character属性,称为isWholeNumber

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的绝佳解决方案!我怎样才能离开“。” 或“,”在字符串中,以便能够将字符串转换为Double?
汉斯·邦多卡

1
@HansBondoka谢谢filter { $0.isNumber || $0 == "." }。尝试这样。
Leo Dabus

11

使用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值,尽管我不希望有任何alpha值
Dan

请更具体。标题说non-alphanumeric;-)我编辑了数字字符的答案。
vadian

8

斯威夫特4

但是没有扩展或componentSeparatedByCharactersInSet,它也不是很好读。

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

4

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

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

3

斯威夫特4.2

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

2

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

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

我不知道字符串中可能包含什么字符-我只想在末尾输入数字值。这将需要我列出所有我不需要的字符。.有很多可能的字符
Dan

2

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: "") } }
xaphod

2

迅捷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"

要么

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

Swift 4.0版本

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

1

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

1

斯威夫特4.2

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

0

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
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.