https://taegon.kim/archives/9919
위 글 공부용
import { escapeRegExp } from 'lodash';
//초성검색
function ch2pattern(ch: string) {
const offset = 44032; // 44032 : '가' 코드
// 한국어 음절에 해당한다면?
if (/[가-힣]/.test(ch)) {
// ch에서 44032를 빼주고
const chCode = ch.charCodeAt(0) - offset;
// 28로 나눠서 떨어지면 중성까지만 있는거고 나머지가 남으면 종성까지 있는거.
if (chCode % 28 > 0) {
// 종성이 있는 경우는 ch를 그대로 반환
return ch;
}
//종성이 없을 때는
const begin = Math.floor(chCode / 28) * 28 + offset; // ex) 돈을 종성 빼버려서 '도'로.
const end = begin + 27; // end는 '돟'
return `[\\u${begin.toString(16)}-\\u${end.toString(16)}]`; // 도~돟에 해당하는 유니코드
}
// 한글 자음만 있을 때는
if (/[ㄱ-ㅎ]/.test(ch)) {
const con2syl = {
ㄱ: '가'.charCodeAt(0),
ㄲ: '까'.charCodeAt(0),
ㄴ: '나'.charCodeAt(0),
ㄷ: '다'.charCodeAt(0),
ㄸ: '따'.charCodeAt(0),
ㄹ: '라'.charCodeAt(0),
ㅁ: '마'.charCodeAt(0),
ㅂ: '바'.charCodeAt(0),
ㅃ: '빠'.charCodeAt(0),
ㅅ: '사'.charCodeAt(0),
};
//as keyof typeof
/*
interface User {
name: string;
age: number;
email: string;
}
keyof typeof User
type UserKeys = "name" | "age" | "email";
*/
// ㄱ~ㅅ 까지는 그대로 begin 주고
// ㅅ 이후로는 해당 유니코드에서 'ㅅ'을 뺀다음 588을 곱하고 다시 ㅅ를 더해서 시작점 설정
// end 는 중성과 종성을 곱해서 더해주기
// ex) ㅎ => begin : 하 end : 힣
const begin =
con2syl[ch as keyof typeof con2syl] ||
(ch.charCodeAt(0) - 12613) * 588 + con2syl['ㅅ']; /* 'ㅅ'의 코드 */
const end = begin + 587;
return `[${ch}\\u${begin.toString(16)}-\\u${end.toString(16)}]`; // ex) 하-힣 에 대한 유니코드 범위
}
// 그 외엔 그대로 내보냄(영어 등등..)
// escapeRegExp : 특수문자 있는 문자열을 정규표현식으로 바꿔주는 메서드(유니코드의 경우 특수문떄문에
// 이스케이프 안하면 에러 뜰 수 있기 때문)
return escapeRegExp(ch);
}
export default function createFuzzyMatcher(input: string) {
const pattern = input.split('').map(ch2pattern).join('.*?');
// 인풋을 하나씩 정규표현식화 시켜서 c a t 이런식으로 만듦.
return new RegExp(pattern);
}