【Swift】语音播报数字转汉字

最近项目需求,要求做语音播报。播报的部分 百度一大堆,我们采用多个语音文件合成+推送扩展的方式。这就涉及到把数字转换为白话文的功能。
比如:-987654300.210 转换成 负9亿8千7百6十5万4千3百点21元
然后录制好每个字符串的语音文件,挨个拼接起来。
实现代码放这里做个记录,顺便要是有类似需求的小伙伴,拿去用就好。这份代码目前支持到999999999999.99,应该够用了。

    
func speakContent(_ price: Double) -> String {
    /// 是否为负数
    let isMinus = price < 0
    
    /// 正负单位
    let minusUnit = isMinus ? "负" : ""
    /// 单位
    let unit = "元"
    
    /// 绝对值
    let absPrice = fabs(price)
    /// 转字符串
    let numberStr = String.init(format: "%.2f", absPrice)
    /// 数字分割
    let cutResult = numberStr.components(separatedBy: ".")
    
    /// 整数部分
    let integralNum = Int(cutResult.first ?? "") ?? 0
    let integralPart = "\(integralNum)"
    
    /// 整数转换结果
    var integralResult = integralPart.enumerated().reduce("") { (accumulate, element) -> String in
        let (index, value) = element
        guard let num = Int(String(value)) else { return "" }
        if num == 0 {
            if accumulate.hasSuffix("0") {
                return accumulate
            }else {
                return accumulate + "0"
            }
        }else {
            let count = integralPart.count - 1 - index
            let unit = self.getUnit(index: count)
            return accumulate + String(value) + unit
        }
    }
    // 移除整数最后一位0
    integralResult.removeLastZero()
    
    /// 小数部分
    let fractionalPart = cutResult.count > 0 ? cutResult.last! : ""
    /// 小数转换结果
    var fractionalResult = fractionalPart.count > 0 ? "点\(fractionalPart)": ""
    // 移除小数最后一位0
    fractionalResult.removeLastZero()
    
    // 最终结果为 正负单位+整数部分+小数部分+单位
    return minusUnit + integralResult + fractionalResult + unit
}

/// 根据位数获取单位名称
/// - Parameter index: 所在位数
/// - Returns: 单位
func getUnit(index: Int) -> String {
    var currentIndex: Int = 0
    if index > 4 && index % 4 > 0 {
        currentIndex = index % 4
    }else {
        currentIndex = index
    }
    switch currentIndex {
    case 1:
        return "十"
    case 2:
        return "百"
    case 3:
        return "千"
    case 4:
        return "万"
    case 8:
        return "亿"
    default:
        return ""
    }
}

// MARK: - Extensions
// Extensions for String
extension String {
    /// 移除最后一位0(只移除一个)
    mutating func removeLastZero() {
        if self.count > 1 && self.last == "0" {
            self = String(self[self.startIndex..<(self.index(self.endIndex, offsetBy: -1))])
        }
    }
}

大体的实现方式就是:
结果由 正负、整数、小数、单位 四个部分组成
正负很简单,判断小于0即可
整数部分需要根据位数插入对应的单位,同时连续存在多个0的需要简化为一个,最后移除末尾的0。
小数部分去除末尾0后直接拼就好

你可能感兴趣的:(【Swift】语音播报数字转汉字)