You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift自定义拼写检查算法求助:无需UITextChecker,支持字符容错

不依赖UITextChecker的拼写检查方案(适配数字混淆场景)

我之前也碰到过类似的需求——不用系统自带的UITextChecker,还要能识别像ce3t这类带数字的拼写错误,把它转换成正确的cat。下面给你一套落地性很强的实现思路和代码:

核心逻辑拆解

这类问题本质是处理输入混淆(数字转字母) + 拼写相似度匹配,分两步走就搞定:

  1. 先把字符串里的数字转换成可能对应的字母(比如3常被误输成a或e,0对应o这类常见混淆),生成所有可能的纯字母候选串;
  2. 用编辑距离(Levenshtein Distance)计算候选串和字典单词的相似度,挑出最匹配的结果。

具体代码实现

1. 先搞个数字-字母混淆映射表

先定义日常输入里最常见的数字转字母的对应关系,你可以根据自己的场景调整:

let numberToLetters: [Character: [Character]] = [
    "0": ["o"],
    "1": ["i", "l"],
    "2": ["z"],
    "3": ["e", "a"], // 对应你例子里的3→a
    "4": ["a"],
    "5": ["s"],
    "6": ["b", "g"],
    "7": ["t"],
    "8": ["b"],
    "9": ["g", "q"]
]

2. 生成所有可能的纯字母候选串

写个递归函数,把带数字的输入转换成所有可能的纯字母组合:

func generatePossibleStrings(from input: String) -> [String] {
    guard let firstChar = input.first else { return [""] }
    let rest = String(input.dropFirst())
    
    let possibleChars: [Character]
    if let letters = numberToLetters[firstChar] {
        possibleChars = letters
    } else {
        possibleChars = [firstChar]
    }
    
    let restStrings = generatePossibleStrings(from: rest)
    return possibleChars.flatMap { char in
        restStrings.map { String(char) + $0 }
    }
}

3. 实现编辑距离计算

编辑距离用来衡量两个字符串的相似度,数值越小越像,这是拼写检查的核心:

func levenshteinDistance(_ s1: String, _ s2: String) -> Int {
    let rows = s1.count + 1
    let cols = s2.count + 1
    
    var distanceMatrix = Array(repeating: Array(repeating: 0, count: cols), count: rows)
    
    // 初始化边界
    for i in 0..<rows {
        distanceMatrix[i][0] = i
    }
    for j in 0..<cols {
        distanceMatrix[0][j] = j
    }
    
    // 填充矩阵
    for i in 1..<rows {
        for j in 1..<cols {
            let s1Char = s1[s1.index(s1.startIndex, offsetBy: i-1)]
            let s2Char = s2[s2.index(s2.startIndex, offsetBy: j-1)]
            let cost = s1Char == s2Char ? 0 : 1
            
            distanceMatrix[i][j] = min(
                distanceMatrix[i-1][j] + 1, // 删除操作
                distanceMatrix[i][j-1] + 1, // 插入操作
                distanceMatrix[i-1][j-1] + cost // 替换操作
            )
        }
    }
    
    return distanceMatrix[rows-1][cols-1]
}

4. 匹配字典里的最佳单词

准备一个常用单词字典(你可以导入本地词库或者用现成的),然后遍历候选串找到最匹配的单词:

func bestMatchingWord(for input: String, dictionary: [String]) -> String? {
    let lowercasedInput = input.lowercased()
    let possibleStrings = generatePossibleStrings(from: lowercasedInput)
    
    var bestWord: String?
    var minDistance = Int.max
    
    for candidate in possibleStrings {
        for word in dictionary {
            let distance = levenshteinDistance(candidate, word.lowercased())
            if distance < minDistance {
                minDistance = distance
                bestWord = word
            }
        }
    }
    
    return bestWord
}

测试一下你的例子

// 随便整个测试用的字典
let testDictionary = ["cat", "dog", "car", "cake", "cent"]
if let result = bestMatchingWord(for: "ce3t", dictionary: testDictionary) {
    print("匹配到的单词:\(result)") // 输出 cat
}

优化小技巧

  • 字典提速:如果字典很大,建议用前缀树(Trie)来代替全量遍历,能大幅提升查找速度;
  • 动态映射:如果是特定场景(比如OCR识别、手机键盘输入),可以调整数字-字母的映射表,加入更多场景化的混淆对应;
  • 阈值过滤:可以设置一个编辑距离阈值,比如超过2就忽略,避免匹配到完全不相关的单词。

内容的提问来源于stack exchange,提问作者Alexyesiam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:56:39