Sae/note

【Codewars】Regexの問題に取り組んだ記録

目次

    毎日codewarsに取り組んでいます!

    codewarsで学んだこと、もう少し深堀して調べたことを残します。
    今回はcodewarsでRegexの問題をいくつかやってみました。

    問題1

    数字が4桁または6桁であればtrueを、否であればfalseを返す関数を実装する

    私の解

    function f(pin) {
      const regex = /(^[0-9]{4}$|^[0-9]{6}$)/gi;
      return regex.test(pin);
    }
    
    console.log(f("1")); // false
    console.log(f("1234")); // true
    console.log(f("a234")); // false
    

    先頭(^)と末尾($)、対象[0-9]が被っている(二回出現している)のが気になる…

    以下は他の方の回答をみて学んだポイント、調べたことをまとめました

    数字の正規表現

    数字は以下の正規表現を使用して表現することができる

    \d
    

    書き換えてみると…

    function f(pin) {
      const regex = /(^\d{4}$|^\d{6}$)/gi;
      return regex.test(pin);
    }
    
    console.log(f("1")); // false
    console.log(f("1234")); // true
    console.log(f("a234")); // false
    

    先頭と末尾以外をグループ化する

    function f(pin) {
      const regex = /^(\d{4}|\d{6})$/g;
      return regex.test(pin);
    }
    
    console.log(f("1")); // false
    console.log(f("1234")); // true
    console.log(f("a234")); // false
    

    問題2

    小文字の英語がいくつ含まれているかを返す関数を実装する

    私の解

    function f(str) {
      const matchedStr = str.match(/[a-z]/g);
      return  matchedStr ? matchedStr.length: 0
    }
    
    console.log(f("abc")); //3
    console.log(f("abcABC123")); //3
    console.log(f("abcABC123!@€£#$%^&*()_-+=}{[]|':;?/>.<,~")); //3
    console.log(f("")); //0
    console.log(f("ABC123!@€£#$%^&*()_-+=}{[]|':;?/>.<,~")); //0
    console.log(f("abcdefghijklmnopqrstuvwxyz")); // 26
    

    問題3

    ハイフン(-)/アンダースコア(_)で区切られた単語をキャメルケースに変換する

    私の解

    ハイフンorアンダースコアの直後に存在するアルファベットを大文字にreplaceしてみたらできそう
    前方一致(?<=)を使用して、表現できそう...!

    function f(str) {
      if (str === "") return "";
      return str
        .replace(/((?<=_)|(?<=-))./g, (a) => a.toUpperCase())
        .split(/_|-/)
        .join("");
    }
    
    console.log(f("the_stealth_warrior"));
    // theStealthWarrior"
    console.log(f("The_stealth_warrior"));
    // TheStealthWarrior
    console.log(f("A-B-C"));
    // ABC
    

    空文字だった場合のif文は不要

    私の書いたコードにある、下記のif文は不要でした

    if (str === "") return "";
    
    function f(str) {
      return str
        // matchするものはないので、replaceされず空文字のまま
        .replace(/((?<=_)|(?<=-))./g, (a) => a.toUpperCase())
        // [""]
        .split(/_|-/)
        .join("");
    }
    console.log(f("")); // ""
    

    キャプチャグループ

    以下のケースだと、(.)にマッチし、マッチした内容を記憶する

    function f(str) {
      return str.replace(/[-_](.)/g, (m, c) => c.toUpperCase());
    }
    

    https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Backreferences

    replace

    replaceの第二引数に関数を渡しましたが、引数にどのようなものが渡ってくるのか。

    function f(str) {
      return str.replace(/[-_](.)/g, (m, c, o, s) => {
        console.log(m, c, o, s);
      });
    }
    f("The_stealth_warrior");
    // _s s 3 The_stealth_warrior
    // _w w 11 The_stealth_warrior
    

    mへは、replaceの第一引数で指定している正規表現にmatchする対象の値が渡り、
    cへはキャプチャされた値(複数ある場合もある)、oはoffsetでmatchした部分の位置を示す。
    sは分析中の対象の文字が渡ることがわかりました

    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace

    まとめ

    今回はRegexに絞ってやっていきました!
    正規表現は苦手意識があるので今後もcodewarsで鍛えていきたいと思います