检测 Swift 字符串中的十进制数

Detect decimal number in Swift string

提问人:dehlen 提问时间:2/23/2023 最后编辑:koendehlen 更新时间:2/23/2023 访问量:84

问:

我想在给定的字符串中检测一个数字。

例如:

  • 1
  • 1.2
  • 1,2
  • 1.2千克
  • 100毫克

请注意,可以肯定的是,字符串始终以数字开头,数字可以是整数或小数,小数分隔符可以是点或逗号。此外,您可以假设字符串不包含多个数字。

从示例中可以看出,字符串也可以包含一个单位。我希望能够获取找到的数字的范围,以便获取剩余的子字符串并将其与已知单位列表进行匹配。但是,该范围应相对于更大的字符串。这里解析的字符串只是一个大得多的字符串的一个标记,我希望能够获得该较大字符串中的数量范围。因此,目标将是一个如下所示的函数:

func scanQuantity(in string: String) -> (NSNumber, Range<String.Index>)?

这是我所拥有的。它有点工作,但是我不确定如何 a) 获取该较大字符串内的数量范围和 b) 如何处理两个小数分隔符,因为 scanDouble 仅适用于一个。

为了更清楚地说明,这就是我想要实现的目标:

I'd like to have 4kg bananas

Tokens: 
- I'd
- like
- to
- have
- 4kg
- bananas

I'd like to have 4kg bananas
                 ↑⇧⇧
↑: quantityRange
⇧: unitRange
func detect(in string: String) {
    let matches = string.matches(of: pattern)
    for match in matches {
        let token = match.output.0
        print("Scanning token: \(token)")
        if let quantity = scanQuantity(in: String(token), of: match.range) {
            print("Found quantity: \(quantity.value)")
        }
    }
}

private func scanQuantity(in token: String, of range: Range<String.Index>) -> Quantity? {
    let scanner = Scanner(string: token)
    #warning("this does not work for both comma and dot decimal separator")
    guard let quantity = scanner.scanDouble() else {
        return nil
    }
    
    if !scanner.isAtEnd {
        let unitSubstring = token[scanner.currentIndex...]
        print("Scanning for unit of quantity")
        print("Unit: \(unitSubstring)")
        #warning("how to get the range of the quantity in the whole string (relative to the range parameter)")
        return Quantity(value: NSNumber(value: quantity), range: range, unit: .piece)
    } else {
        return Quantity(value: NSNumber(value: quantity), range: range, unit: .piece)
    }
}
快速 解析

评论


答:

0赞 Joakim Danielson 2/23/2023 #1

您可以在 swift 中使用新功能Regex

使用的模式是

let regex = /((\d+(\.|,?)\d*)([a-z]*))/

然后计算正则表达式

someString.firstMatch(of: regex)

let inputs = ["1", "1.2", "1,2", "1.2kg", "100mg", "I'd like to have 4kg bananas"]

for input in inputs {
    if let result = input.firstMatch(of: regex) {
        print((result.2, result.4))
    }
}

输出

("1", "")
(“1.2”, “”) (“1,2”, “”) (“1.2”, “公斤”) (“100”, “毫克”) (“4”, “公斤”)