如何使用Unicode标量将字符串转换为CGFloat

How to convert string with Unicode Scalar to CGFloat

提问人:Moses Harding 提问时间:9/27/2023 更新时间:9/27/2023 访问量:33

问:

我有一个可以包含任意值的字符串;例如,它可能是“1”、“11/2”,也可能是“一”。

如果是数字,我想将其转换为浮点数。如果只是“1”,这很简单

if let newFloat = NumberFormatter().number(from: string) {
    let float = CGFloat(truncating: newFloat)
    print(float)
}

但如果是“1/2”,则该代码将失败。

我对 String 进行了扩展,它将找到“粗俗分数”并将它们替换为小数。它确实有效,但是 1.感觉很骇人听闻,而且 2.它不考虑部分分数,这意味着字符串“11/3”输出为“10.333”。我已经把它粘贴在下面 - 有没有更好的方法可以做到这一点?

extension String {
    func replaceVulgarFractions() -> String {
        var modifiedText = self
        
        let vulgarFractionRegex = "[½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅛⅜⅝⅞]"
        
        while let matchRange = modifiedText.range(of: vulgarFractionRegex, options: .regularExpression) {
            let matchedFraction = String(modifiedText[matchRange])
            if let decimalValue = matchedFraction.vulgarFractionToDecimal() {
                modifiedText = modifiedText.replacingCharacters(in: matchRange, with: String(format: "%.3f", decimalValue))
            }
        }
        
        return modifiedText
    }
    
    func vulgarFractionToDecimal() -> Double? {
        switch self {
        case "½": return 0.5
        case "⅓": return 1.0 / 3.0
        case "⅔": return 2.0 / 3.0
        case "¼": return 0.25
        case "¾": return 0.75
        case "⅕": return 0.2
        case "⅖": return 0.4
        case "⅗": return 0.6
        case "⅘": return 0.8
        case "⅙": return 1.0 / 6.0
        case "⅚": return 5.0 / 6.0
        case "⅐": return 1.0 / 7.0
        case "⅛": return 1.0 / 8.0
        case "⅜": return 3.0 / 8.0
        case "⅝": return 5.0 / 8.0
        case "⅞": return 7.0 / 8.0
        default: return nil
        }
    }
}
swift 字符串 unicode

评论


答:

0赞 HangarRash 9/27/2023 #1

我没有看到任何内置方法可以将粗俗的分数字符转换为小数。一种解决方案是修复代码以调整字符串格式的前导。0

使用以下代码更新循环:while

while let matchRange = modifiedText.range(of: vulgarFractionRegex, options: .regularExpression) {
    let matchedFraction = String(modifiedText[matchRange])
    if let decimalValue = matchedFraction.vulgarFractionToDecimal() {
        var fracStr = String(format: "%3.3f", decimalValue) // Your original format
        // Remove the leading zero unless this is the first character
        if fracStr.hasPrefix("0.") && matchRange.lowerBound != modifiedText.startIndex {
            fracStr = String(fracStr.dropFirst())
        }
        modifiedText = modifiedText.replacingCharacters(in: matchRange, with: fracStr)
    }
}

此代码从字符串格式的结果中删除任何前导零,除非这是来自原始字符串的第一个字符。

这些更改将为“11/2”提供“1.5”,为“1/2”提供“0.5”。