You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
5.1 KiB
196 lines
5.1 KiB
let allPinyin = []
|
|
let notone = {};
|
|
let storage = {}
|
|
|
|
function init(dict) {
|
|
// https://github.com/xmflswood/pinyin-match/issues/37
|
|
const handledDict = {}
|
|
const uv = ['ju','jun','jue','juan','qu','qun','que','xuan','xu','xue','yu','yuan','yue','yun','nve','lve']
|
|
// https://github.com/xmflswood/pinyin-match/pull/43
|
|
const vList = ['lv', 'lve', 'nv', 'nve']
|
|
Object.keys(dict).forEach(key => {
|
|
handledDict[key] = dict[key]
|
|
allPinyin.push(key)
|
|
if (uv.includes(key)) {
|
|
const replacedKey = replaceUv(key)
|
|
handledDict[replacedKey] = dict[key]
|
|
allPinyin.push(replacedKey)
|
|
}
|
|
if (vList.includes(key)) {
|
|
const replacedKey = key.replace('v', 'ü')
|
|
handledDict[replacedKey] = dict[key]
|
|
allPinyin.push(replacedKey)
|
|
}
|
|
})
|
|
notone = parseDict(handledDict)
|
|
return match
|
|
}
|
|
function replaceUv(str) {
|
|
if (str.indexOf('u') !== -1) return str.replace('u', 'v')
|
|
return str.replace('v', 'u')
|
|
}
|
|
|
|
function parseDict(dict) {
|
|
let parseDict = {}
|
|
for (let i in dict) {
|
|
let temp = dict[i]
|
|
for (let j = 0, len = temp.length; j < len; j++) {
|
|
if (!parseDict[temp[j]]) {
|
|
parseDict[temp[j]] = i
|
|
} else {
|
|
parseDict[temp[j]] = parseDict[temp[j]] + ' ' + i
|
|
}
|
|
}
|
|
}
|
|
return parseDict
|
|
}
|
|
|
|
function getPinyin(cn) {
|
|
let result = []
|
|
for (let i = 0, len = cn.length; i < len; i++) {
|
|
let temp = cn.charAt(i)
|
|
result.push(notone[temp] || temp)
|
|
}
|
|
return result
|
|
}
|
|
// 对输入拼音进行切分
|
|
function wordBreak(s) {
|
|
let result = []
|
|
let solutions = []
|
|
let len = s.length
|
|
let possible = []
|
|
for (let i = 0; i <= len; i++) {
|
|
possible.push(true)
|
|
}
|
|
getAllSolutions(0, s, result, solutions, possible)
|
|
return solutions
|
|
}
|
|
|
|
function getAllSolutions(start, s, result, solutions, possible) {
|
|
let len = s.length
|
|
if (start === len) {
|
|
solutions.push(result.join(' '))
|
|
return
|
|
}
|
|
for (let i = start; i < len; i++) {
|
|
let piece = s.substring(start, i + 1)
|
|
let match = false
|
|
// 最后一个音特殊处理,不需要全部打完整
|
|
if (allPinyin.some(i => i.indexOf(piece) === 0) && !s[i + 1] && possible[i + 1]) {
|
|
if (piece.length === 1) {
|
|
result.push(piece)
|
|
} else {
|
|
let s = []
|
|
allPinyin.forEach(i => {
|
|
if (i.indexOf(piece) === 0) {
|
|
s.push(i)
|
|
}
|
|
})
|
|
result.push(s)
|
|
}
|
|
match = true
|
|
} else {
|
|
if (allPinyin.indexOf(piece) !== -1 && possible[i + 1]) {
|
|
result.push(piece)
|
|
match = true
|
|
}
|
|
}
|
|
if (match) {
|
|
let beforeChange = solutions.length
|
|
getAllSolutions(i + 1, s, result, solutions, possible)
|
|
if (solutions.length === beforeChange) {
|
|
possible[i + 1] = false
|
|
}
|
|
result.pop()
|
|
}
|
|
}
|
|
}
|
|
// 获取输入拼音的所有组合(切分 + 首字母)
|
|
function getFullKey(key) {
|
|
let result = []
|
|
wordBreak(key).forEach(i => {
|
|
let item = i.split(' ')
|
|
let last = item.length - 1
|
|
if (item[last].indexOf(',')) {
|
|
let keys = item[last].split(',')
|
|
keys.forEach(j => {
|
|
item.splice(last, 1, j)
|
|
result.push(JSON.parse(JSON.stringify(item)))
|
|
})
|
|
} else {
|
|
result.push(item)
|
|
}
|
|
})
|
|
if (result.length === 0 || (result[0].length !== key.length)) {
|
|
result.push(key.split(''))
|
|
}
|
|
// 缓存当前结果 避免重复计算
|
|
storage = {[key]: result}
|
|
return result
|
|
}
|
|
function point2point(test, key, last, extend) {
|
|
if (!test) return false
|
|
let a = test.split(' ')
|
|
a.forEach(i => {
|
|
if (i.length > 0 && extend) {
|
|
a.push(i.charAt(0))
|
|
}
|
|
})
|
|
if (!last) {
|
|
return a.indexOf(key) !== -1
|
|
}
|
|
return a.some((i) => i.indexOf(key) === 0)
|
|
}
|
|
|
|
function match(input, keys) {
|
|
if (!input || !keys) return false
|
|
input = input.toLowerCase()
|
|
keys = keys.replace(/\s+/g, '').toLowerCase()
|
|
let indexOf = input.indexOf(keys)
|
|
if (indexOf !== -1) {
|
|
return [indexOf, indexOf + keys.length - 1]
|
|
}
|
|
// 原文匹配(带空格)
|
|
let noPyIndex = getIndex(input.split(''), [keys.split('')], keys)
|
|
if (noPyIndex) return noPyIndex
|
|
// pinyin匹配
|
|
let py = getPinyin(input)
|
|
let fullString = storage[keys] || getFullKey(keys)
|
|
return getIndex(py, fullString, keys)
|
|
}
|
|
function getIndex(py, fullString, keys) {
|
|
for (let p = 0; p < py.length; p++) {
|
|
for (let k = 0; k < fullString.length; k++) {
|
|
let key = fullString[k]
|
|
let keyLength = key.length
|
|
let extend = (keyLength === keys.length)
|
|
let isMatch = true
|
|
let i = 0
|
|
let preSpaceNum = 0
|
|
let spaceNum = 0
|
|
if (keyLength <= py.length) {
|
|
for (; i < key.length; i++) {
|
|
if (i === 0 && py[p + i + preSpaceNum] === ' ') {
|
|
preSpaceNum += 1
|
|
i -= 1
|
|
} else {
|
|
if (py[p + i + spaceNum] === ' ') {
|
|
spaceNum += 1
|
|
i -= 1
|
|
} else {
|
|
if (!point2point(py[p + i + spaceNum], key[i], (py[p + i + 1] && key[i + 1]) ? false : true, extend)) {
|
|
isMatch = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (isMatch) {
|
|
return [p + preSpaceNum, spaceNum + p + i - 1]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
export default init
|