Javascript

[Javascript] 문자열 내 초성 검색 하이라이트 효과주기

chsr 2021. 11. 3. 15:04
728x90
반응형

■ Javascript 문자열 내 초성 검색 하이라이트 효과주기

문자열 또는 문장 내 검색한 초성과 일치하는 단어에 하이라이터 효과 처리


예제 순서

1. 검색어와 비교문자열 모두 초성으로 변환시킨다.
2. 비교할 문자열에서 검색한 문자열이 포함될 수 있는 위치의 인덱스를 모두 구해온다.
3. 구한 인덱스들을 반복 시키면서 비교문자열에서 해당 인덱스 위치 부터 검색어의 길이만큼 가져온다 -> 초성으로 바꾼 검색어와 같은 문자열이 나옴
4. 검색어가 초성이 아닌 글자의 인덱스를 찾고
5. 초성으로 변환한 비교 문자열의 위에서 나온 인덱스의 문자를 원본 비교문자로 치환
6. 5번 결과의 문자열과 원본 검색어를 비교해 일치 시 반환


 예제

// 문자열 초성으로 변환
function cho(str){
    var res = ""; // 초성으로 변환
    var choArr = ["ㄱ","ㄲ","ㄴ","ㄷ","ㄸ","ㄹ","ㅁ","ㅂ","ㅃ","ㅅ","ㅆ","ㅇ","ㅈ","ㅉ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ"];
 
    for( var i in str ){
        code = Math.floor((str[i].charCodeAt() - 44032) / 588);
        res += code >= 0 ? choArr[code] : str[i];
    }
    return res;
}
 
var compars = ["가나다라", "나다", "가나", "가", "다다두다", "두두두다다다", "다라", "ㄷㄷ"], // 검색 데이터
var searchArr = 'ㄷㄷ두다', // 검색어
var res = []; // 검색 결과
 
var searchArr = searchArr.split('|');
 
searchArr.forEach((search, t) => {
    var searchCho = cho(search);
    /*
        1. 검색어와 비교문자열 모두 초성으로 변환시킨다.
        2. 비교할 문자열에서 검색한 문자열이 포함될 수 있는 위치의 인덱스를 모두 구해온다.
        3. 구한 인덱스들을 반복 시키면서 비교문자열에서 해당 인덱스 위치 부터 검색어의 길이만큼 가져온다 -> 초성으로 바꾼 검색어와 같은 문자열이 나옴
        4. 검색어가 초성이 아닌 글자의 인덱스를 찾고
        5. 초성으로 변환한 비교 문자열의 위에서 나온 인덱스의 문자를 원본 비교문자로 치환
        6. 5번 결과의 문자열과 원본 검색어를 비교해 일치 시 반환
    */
 
    compars.forEach((compare, i) => {
        var compCho = cho(compare); // 비교문자의 초성
        var strIdxs = [], // 비교문자열에서 검색어와 일치하는 부분의 시작 위치
        var compare = compare.split(''); // 비교문자
 
        for( var c in compCho ){ // 검색어, 비교문자를 초성으로 변환후 일치하는 부분 모두 찾기
            /*
                비교할 문자 : ㄱㄱㄱㄱㄱㄱㄱ
                검색어 : ㄱㄱㄱㄱ일때 
                검색어가 비교할 문자열에 몇번째 문자열에 포함될 수 있는지 모두 구해옴
                0,1,2,3 번째 문자열에 들어갈 수 있음
            */
            var idx = compCho.indexOf(searchCho, c); // 일치하는 부분의 인덱스
 
            if( idx != -1 && strIdxs.indexOf(idx) == -1 ){
                strIdxs.push(idx);
            }
        }
        chk = 0;
        
        strIdxs.forEach((idx, d) => {
            var str = searchCho.split('');
 
            for( var e in search ){
                if( search[e].charCodeAt() - 44032 >= 0 ) // 검색어중에 초성이 아닌부분
                    str[e] = compare[idx + e * 1]; // 초성변환 전의 문자로 치환
            }
 
            if( str.join('') == search ){ // 비교문자
                chk = 1;
                for( var q = idx; q < idx + search.length; q++ ){
                    compare[q] = `<span style='background: yellow'>${compare[q]}</span>` // 비교문자 하이라이트
                }
            }
        })            
 
        if( chk ){
            res.push(compare.join(''));
        }
    })
});
 
res.forEach((el, ix) => {
    document.getElementById("ul").innerHTML += "<li>"+el+"</li>"
});

 

참고 https://wmsttks.tistory.com/28

728x90
반응형