Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Parsing fractions from text
import UIKit
let fractionRegExPattern = #"(?<neg>-?){0,1}(?:\s){0,1}(?:(?<whole>\d+)\s)?(?<numerator>\d+)\/(?<denominator>\d+)"#
func parseResult(_ match:NSTextCheckingResult, canidateString:String) -> (Int?, Int, Int) {
var mulitplier = 1
var wholeNumber: Int?
var numerator: Int?
var denominator: Int?
if canidateString[(Range(match.range(withName: "neg"), in: canidateString)!)] == "-" {
mulitplier = -1
print("negative!")
}
if let wholeNumberRange = Range(match.range(withName: "whole"), in: canidateString) {
wholeNumber = Int(canidateString[wholeNumberRange])
if wholeNumber != nil {
wholeNumber = wholeNumber! * mulitplier
}
}
if let numeratorRange = Range(match.range(withName: "numerator"), in: canidateString) {
numerator = Int(canidateString[numeratorRange])
if wholeNumber == nil {
numerator = numerator! * mulitplier
}
}
if let denominatorRange = Range(match.range(withName: "denominator"), in: canidateString) {
denominator = Int(canidateString[denominatorRange])
}
if numerator == nil || denominator == nil {
fatalError("how did they not get found???!!!")
}
return (whole:wholeNumber, numerator:numerator!, denominator:denominator!)
}
func findAll(in canidateString:String) -> [(whole:Int?, numerator:Int, denominator:Int)] {
let regex = try? NSRegularExpression(pattern: fractionRegExPattern, options: .caseInsensitive)
var foundFractions:[(whole:Int?, numerator:Int, denominator:Int)] = []
if let matches = regex?.matches(in: canidateString, options: [], range: NSRange(location: 0, length: canidateString.utf16.count)) {
for m in 0..<matches.count {
foundFractions.append(parseResult(matches[m], canidateString: canidateString))
}
}
return foundFractions
}
func findFirst(in canidateString:String) -> (whole:Int?, numerator:Int, denominator:Int)? {
guard let regex = try? NSRegularExpression(pattern: fractionRegExPattern, options: .caseInsensitive) else {
print("bad regex")
return nil
}
if let match = regex.firstMatch(in: canidateString, options: [], range: NSRange(location: 0, length: canidateString.utf16.count)) {
return parseResult(match, canidateString: canidateString)
}
return nil
}
let testStrings = [
"8 3/4",
"-5 32/12 in",
"-5/7",
"- 7 3/32",
"approx. - 9/12",
"12",
"Between 1/4 and 3/16th"
]
for string in testStrings {
print(findFirst(string))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment