Issue #781
This sounds like an easy task, but a quick search on Stackoverflow results in this with highest votes https://stackoverflow.com/questions/29971505/filter-non-digits-from-string
CharacterSet.decimalDigits contains more than just digits
This splits a string by inverted set of decimalDigits
and join them back.
extension String {
var digits: String {
return components(separatedBy: CharacterSet.decimalDigits.inverted)
.joined()
}
}
Reading decimalDigits
Informally, this set is the set of all characters used to represent the decimal values 0 through 9. These characters include, for example, the decimal digits of the Indic scripts and Arabic.
So decimalDigits
does not only contain digits, but also some scripts in other languages. For normal cases this should not be a problem. As How many decimal digits are there, anyways?
there are 610 valid characters in CharacterSet.decimalDigits
. So be aware
let s = CharacterSet.decimalDigits
// U+0031 DIGIT ONE
s.contains("1") // true as expected
// U+1D7D9 MATHEMATICAL DOUBLE-STRUCK DIGIT ONE
s.contains("𝟙") // true!
// U+0967 DEVANAGARI DIGIT ONE
s.contains("१") // true!
// U+1811 MONGOLIAN DIGIT ONE
s.contains("᠑") // true!
Trimming
Another method is trimmingCharacters. Note that this removes only characters at the start and end of the string.
string.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789").inverted)
Just filter
A boring but correct solution is to filter characters anywhere in the string.
string.filter("0123456789".contains)
This is more performant than components
then join
below
string.components(separatedBy: CharacterSet(charactersIn: "0123456789").inverted).joined()