如何对对象数组的属性做拼写检查以实现指定规则的名称匹配
功能实现方案
核心规则梳理
先明确你需要的匹配逻辑:
- 大小写不敏感
- 按词位置一一对应校验相似度,不可跨词位匹配
- 至少1个词位满足近似匹配要求,该条数据才返回
- 多词输入、多词name场景通用
实现步骤
1. 编写相似度判断方法
我们用编辑距离(莱文斯坦距离)判断两个单词的拼写近似度,你可以根据业务需求调整阈值,比如示例场景可以加短单词严格匹配的规则,避免Ma和Man这种短单词的误差:
// 计算两个字符串的莱文斯坦距离 function getLevenshteinDistance(a, b) { const matrix = Array.from({ length: a.length + 1 }, () => Array(b.length + 1).fill(0)) for (let i = 0; i <= a.length; i++) matrix[i][0] = i for (let j = 0; j <= b.length; j++) matrix[0][j] = j for (let i = 1; i <= a.length; i++) { for (let j = 1; j <= b.length; j++) { const cost = a[i - 1] === b[j - 1] ? 0 : 1 matrix[i][j] = Math.min( matrix[i - 1][j] + 1, // 删除 matrix[i][j - 1] + 1, // 插入 matrix[i - 1][j - 1] + cost // 替换 ) } } return matrix[a.length][b.length] } // 自定义近似匹配判断 function isSimilar(a, b) { // 统一转小写,消除大小写差异 const strA = a.toLowerCase() const strB = b.toLowerCase() // 长度小于等于3的单词要求完全匹配,符合你示例中排除Jacky Man的需求 if (strA.length <= 3 || strB.length <= 3) { return strA === strB } // 长单词允许1个字符的误差(增删改) return getLevenshteinDistance(strA, strB) <= 1 }
2. 编写核心匹配逻辑
function fuzzySearchName(inputName, database) { // 预处理输入的搜索词,拆分单词、过滤多余空格 const inputWords = inputName.toLowerCase().split(' ').filter(Boolean) if (inputWords.length === 0) return [] return database.filter(item => { // 预处理当前条目的name const itemWords = item.name.toLowerCase().split(' ').filter(Boolean) // 取两个单词数组的最小长度,按词位逐一匹配 const minLen = Math.min(inputWords.length, itemWords.length) let hasMatch = false for (let i = 0; i < minLen; i++) { if (isSimilar(inputWords[i], itemWords[i])) { hasMatch = true break } } return hasMatch }) }
测试效果
用你提供的示例数据测试:
const database = [ { name: "Jacky Ma" }, { name: "Jacky Man" }, { name: "Jack Mun" }, { name: "Jacob Ma" }, { name: "Jack Ma" } ] const result = fuzzySearchName("Jack Ma", database) console.log(result) // 输出:[{name: "Jacky Ma"}, {name: "Jack Mun"}, {name: "Jacob Ma"}, {name: "Jack Ma"}]
如果你需要排除完全匹配的Jack Ma,可以在过滤逻辑里增加全匹配校验规则即可。
内容的提问来源于stack exchange,提问作者Tech And Gaming
相关产品推荐
相关产品推荐

