正規表現と分類の問題<新しいアイデンティティの推奨>


プログラマーが提供するコードテストLv 1の問題を解くために、「新しいアイデンティティ推奨」は、正規表現を学び、実戦に応用し、大きな助けを得た.学習内容を整理し、刻印させる.

📝 正規表現の学習


JavaScriptでは、正規表現(以下、正規表現と略す)を作成するには、3つの方法があります.
<script>
// 1. 정규식 리터럴 (슬래쉬로 감싸기)
const exp = /ab+c/g;
// 2. RegExp 리터럴
const exp1 = new RegExp(/ab+c/, 'g');
// 3. RegExp 생성자
const exp2 = new RegExp('ab+c', 'g');
</script>

特殊文字

  • (反スラッシュ):特殊文字以外(特殊文字以外)の前に使用する場合は、「この文字は特別に使用する必要があります」を示します.逆に、特殊文字の前に使うと、「この文字は特別ではなく、文字に従って解釈しなければならない」という意味になります./a*/->0個のa繰返し/a\*/->文字列「a*」は
  • に対応
    RegExpジェネレータ方式を使用する場合、はそれ自体をエスケープする必要があります.すなわち、通常文字またはRegExp文字では/a\*/で表すことができ、RegExpジェネレータでは'a\\*'で表すべきである.正確な理由は分かりませんが、文字列の中のの解釈による問題かもしれません.

  • {n}(カッコ):前の式nに対応します.
    ex)/a{2}/は、文字列「caandy」のaa、「caaaandy」の最初のaaに対応する.

  • *:前の式と連続して0回以上繰り返した部分に対応します.等しい.
    ex)/ab*c/は、文字列「abbbc」のabbbcに対応する.aとcの間で繰り返されるbでなければならない.

  • +:前の式と連続して1回以上繰り返した部分に対応します.等しい.
    ex)`/a+/は、文字列「caaaandy」のすべてのaに対応する.

  • ? : 前の式は、0または1回に現れる部分に対応しています.は、{0,1}に等しい.
    ex)/e?le?/は、文字列「angel」のel、「oslo」のlに対応する.

  • ^:入力された最初の文字に対応します.
    ex)/^A/は、文字列「ANE」のAに対応する.

  • $:入力の終了文字に対応します.
    ex)/t$/は、文字列「eat」のtに対応する.
  • /^$/は空の文字列を表します.

  • .:先頭文字以外のすべての単一文字に対応します.
    ex)/.n/は、文字列「nay,an apple is on the tree」のanおよびonに対応する.

  • (x)(かっこ):グループ化とキャプチャ機能があります.

  • x|y:xまたはy対応

  • {n,m}:前の文字が最低n回、最大m回繰り返された部分に対応します.このときnとmは正の整数でなければならず、n<=mを満たす.

  • [xyz]:文字セット(文字セット).文字セットの内部では、特殊文字は通常の文字に対応します.そのため、エスケープする必要はありません.文字セット内では、ハイフンを使用して文字の範囲を指定できます.
    ex)/[a-d]//[abcd]/と同じです.対応文字列「brisket」のb、「city」のc./[a-z.]+/は文字列「test」です.i.ngでは全体に対応する.

  • [^xyz]:否定文字セット(否定)または補足文字セット(相補)と呼ばれます.かっこ内に表示されないすべての文字に対応します.
    ex)/[^a-c]/gは、文字列「brisket」のrisketに対応する.

  • [\b]:backspace.bと混同してはいけない.

  • b:単語の境界.単語文字/[A-Za-z0-9_]/に対応する単語間の境界(スペースなど).
    ex)/\b[a-z]/gは、文字列「you like me」のy,l,mに対応する.

  • w:単語文字.下線文字を含むアルファベットと数値に対応します.
    ex)/\w/gは、文字列「$5.28,」の5.28に対応する.
  • 方法


    String.replace()


    String.replace()関数は、1番目のパラメータとして渡されるパターンに一致する部分を2番目のパラメータとして渡される形式に変更します.
    2番目のパラメータ伝達関数を使用する場合は、1番目のパラメータ伝達の正規表現を使用して一致した後に関数が呼び出されます.
    ex)'you like me'.replace(/\b[a-z]/g, char => char.toUpperCase())の結果は「YouLikeMe」です.

    🖥️ 実戦応用


    上記の正規文法だけを知っていても、『新ID推薦』の問題を解決するのに十分です.これは,特定の条件に基づいて入力の乱雑な考え方を簡略化する問題である.
    手順1 new idのすべての大文字を対応する小文字に置き換えます.
    ステップ2 new idでは、小文字、数字、マイナス記号(-)、下線()および句点(.)以外のすべての文字を削除します.
    ステップ3 new idのピリオド(.)1つのポイント(.)に置き換えます.
    ステップ4 new idのピリオド(.)先頭または末尾にある場合は削除します.
    ステップ5 new idが空の文字列の場合、new idに「a」を挿入します.
    ステップ6 new idの長さが16文字を超える場合、new idの最初の15文字以外のすべての他の文字を削除します.
    削除後のピリオド(.)new idの末尾にある場合、終了記号(.)テキストを削除します.
    ステップ7のnew idの長さが2文字未満の場合、new idの長さが3になるまで、new idの最後の文字を最後に繰り返し貼り付けます.
    最初に作成したコードは以下の通りです.うまく記述されたコードとは言えないが,1つ1つの正規式でテストを行い,より速い速度でコードを記述した.
    <script>
    function solution(new_id) {
        
        // 1) 대문자 -> 소문자
        const first = new_id.toLowerCase();
        console.log(first);
        
        // 2) 소문자 알파벳, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자 제거
        // match는 결과를 Array로 반환한다. join('')을 이용해서 배열을 구분자 없이 문자열로 변환한다.
        let regex = /[a-z0-9-_.]/g;
        const second = first.match(regex).join('');
        console.log(second);
        
        // 3) 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표로 치환
        // regex = /.+/g;  // Fail
        regex = /\.{2,}/g;
        const third = second.replace(regex, '.');
        console.log(third);
        
        // 4) 마침표가 처음이나 끝에 위치하면 제거한다
        regex = /^(\.)|(\.)$/g;
        const fourth = third.replace(regex, '');
        console.log(`${fourth}`);
        
        // 5) 빈 문자열이면 a를 대입
        let fifth;
        fourth === "" ? fifth = 'a' : fifth = fourth;
        console.log(fifth);
        
        // 6) 길이가 16자 이상이면, 첫 15개를 제외한 나머지 문자를 제거.
        // 만약 제거 후 마침표가 문자열 끝에 위치한다면, 마침표를 제거.
        let sixth;
        fifth.length >= 16 
            ? sixth = fifth.substr(0,15)
            : sixth = fifth;
        
        regex = /\.$/g;
        sixth = sixth.replace(regex, '');
        console.log(sixth);
        
        // 7) 길이가 2자 이하라면, 마지막 문자를 길이 3이 될 때까지 반복.
        if(sixth.length <= 2){
            while(sixth.length < 3)
                sixth += sixth[sixth.length-1];
        }
        console.log(sixth);
        return sixth;
    }
    </script>
    次に他の人が作ったコードを見て、少し変更しました.正規表現/^$/は、空の文字列およびStringを表す.repeat()メソッドをよく見ました.
    <script>
    function solution(new_id){
        const answer = new_id
            .toLowerCase() // 1
            .replace(/[^a-z0-9-_.]/g, '') // 2
            .replace(/\.{2,}/g, '.') // 3
            .replace(/^(\.)|(\.)$/g, '') // 4
            .replace(/^$/g, 'a') // 5 /^$/은 빈 문자열을 의미한다
            .slice(0,15).replace(/\.$/g, ''); // 6
        
        const len = answer.length;
        return len > 2 ? answer : answer + answer.charAt(len-1).repeat(3 - len);
    }
    </script>

    📚 Reference


    MDN-正規表現
    MDN - RegExp