한글 초성 검색은 여기저기서 사용할 필요가 생깁니다.
초성 검색이라고하면,
예를 들어 "테스트"라는 String을 검색할 때, "ㅌㅅㅌ"로 검색해도 검색이 되도록 하는 기능이구요.
스마트폰 전화번호부 검색 등에서 한 번은 써보셨을겁니다.
이번 포스팅에서는 Dart로 해당 코드를 구현해보겠습니다.
먼저 전체 코드입니다.
bool contains_initialConsonant(String string, String query) {
/*
Hangul UTF16 structure :
① Hangul characters start from 44032(== '가').
② A group of same initial consonant has 588 characters.
③ Initial consonants are 19ea,
such as 'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
④ Hangul initial consonant characters start from 12593 to 12622
'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ',
*/
const codeOfFirstHangulLetter = 44032;
const numberOfSameInitialConsonant = 588;
final initialConsonants = [
'ㄱ',
'ㄲ',
'ㄴ',
'ㄷ',
'ㄸ',
'ㄹ',
'ㅁ',
'ㅂ',
'ㅃ',
'ㅅ',
'ㅆ',
'ㅇ',
'ㅈ',
'ㅉ',
'ㅊ',
'ㅋ',
'ㅌ',
'ㅍ',
'ㅎ'
];
if (string.length < query.length) {
return false;
}
if (query.isEmpty) return true;
for (int i = 0; i < string.length - query.length + 1; i++) {
bool contains = true;
for (int j = 0; j < query.length; j++) {
if (initialConsonants.contains(query.substring(j, j + 1))) {
if ((string.substring(i + j, i + j + 1).codeUnitAt(0) -
codeOfFirstHangulLetter) ~/
numberOfSameInitialConsonant !=
initialConsonants.indexOf(query.substring(j, j + 1))) {
contains = false;
break;
}
} else {
if (query.substring(j, j + 1) != string.substring(i + j, i + j + 1)) {
contains = false;
break;
}
}
}
if (contains) return true;
}
return false;
}
구현 방법은 그리 복잡하지않습니다.
우선, Dart에서는 아래와 같이 codeUnitAt() method로 String의 UTF16 BE(Big Endian) 코드를 간단히 구할 수 있습니다.
print('가'.codeUnitAt(0)); // result will be 44032
두번째로, 한글의 UTF16 BE 기준 코드 구조를 보면,
① '가' → 44032, '까' → 44620, '나' → 45208 과 같이 44032부터 시작해서 각 초성별로 588개의 글자가 존재합니다.
② 초성의 순서는 아래와 같습니다.
'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
③ 위의 2가지 특성을 잘 이용해보면,
특정 한글 글자의 UTF16 코드에서 44032를 빼고,
다시 588로 나누면 ②에 표시한 초성 배열의 위치가 나오게됩니다.
마지막으로 실제 주어진 string에 query가 포함되어 있는지 포함하는 방법은 아래 순서입니다.
① 우선 검색하려는 query의 길이가 검색대상인 string보다 길면 false를 return합니다.
② query의 길이가 0이라면 true를 return합니다.
③ string과 query의 2중 for문으로 각 글자별로 비교를 진행합니다.
④ query의 현재 비교 글자가 한글 자모인지를 판단한 후,
맞다면 string의 해당 글자를 자모로 변경해서 비교,
다르다면 직접 비교합니다.
단순한 코드니 잘 보시면 이해하시는데 어려움이 없을 듯 합니다.
오늘은 여기까지입니다.
좋은 하루 되세요~
'Programming' 카테고리의 다른 글
[Autohotkey] Numbering powerpoint pages (0) | 2025.04.06 |
---|---|
Regular Expression(정규식) (0) | 2022.11.16 |
GitHub : Flutter Web app을 GitHub Pages를 이용해 Deploy하기 2/2 (0) | 2022.10.02 |
GitHub : Flutter Web app을 GitHub Pages를 이용해 Deploy하기 1/2 (0) | 2022.10.02 |
GitHub : GitHub 에서 Source code 가져오기 (Clone) (0) | 2022.10.01 |