NSFormatter's spellout
method lets you convert a word into a number. NSString's stringByReplacingOccurrencesOfString
lets you convert strings such as thousand into 1000. And you can pick integers out of strings using NSCharacterSet
. However, I am struggling with how to convert a mixture of numbers and strings, for example, about 2.4 million
or the comes to 5 hundred
into a number. The problem is isolating the '2.4 million' from the 'about' or other text.
Applying spellout to "2.4 million" yields 2400000. However, applying it to "about 2.4 million" gives an error.
extension NSString {
public var asNum: NSNumber {
// let stringValue = String(value: self)
let stringValue = self
let formatter = NumberFormatter()
formatter.isLenient = true
formatter.numberStyle = .spellOut
return formatter.number(from: stringValue as String) ?? -1
}
}
How can I isolate just the terms that are part of a valid number?
If you used a regular expression you could extract just the string with the numeric expression. Assuming that the extra words are at the beginning (as you said in a comment) you can do the following:
\d+(\.\d+)*\s+\w+
range.location != NSNotFound
String
You can add just three lines to your code and it should work fine, something like this:
extension NSString {
public var asNum: NSNumber {
let stringValue = self
let range = stringValue.range(of: #"\d+(\.\d+)*\s+\w+"#,
options: .regularExpression)
guard range.location != NSNotFound else { return -1 }
let numberExpression = stringValue.substring(with: range)
let formatter = NumberFormatter()
formatter.isLenient = true
formatter.numberStyle = .spellOut
return formatter.number(from: numberExpression) ?? -1
}
}
If we follow @rmaaddy suggestion of returning an optional instead of the "magic number" -1 then the code looks like this:
extension NSString {
public var asNum: NSNumber? {
let stringValue = self
let range = stringValue.range(of: #"\d+(\.\d+)*\s+\w+"#,
options: .regularExpression)
guard range.location != NSNotFound else { return nil }
let numberExpression = stringValue.substring(with: range)
let formatter = NumberFormatter()
formatter.isLenient = true
formatter.numberStyle = .spellOut
return formatter.number(from: numberExpression) ?? nil
}
}