<- Back to list

codewars | JS で アルファベットを順番の番号に置き換え

codewarsJavaScript

今回の問題:JS | アルファベットを順番の番号に置き換える

日本語ではまた違う話になりそうですが、アルファベットのテキストを、アルファベットの順番の番号に変換する関数です。

問題

In this kata you are required to, given a string, replace every letter with its position in the alphabet.
If anything in the text isn't a letter, ignore it and don't return it.

alphabetPosition("The sunset sets at twelve o' clock.") // "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11"

私の回答

function alphabetPosition(text) { const arr = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']; const textArr = text.toLowerCase().split(''); // 小文字にしてから1文字ずつの配列に let result = []; textArr.forEach((item, index) => { arr.forEach((item2, index2) => { if(item2 === item) { result.push(index2 + 1) } }) }) result = result.join().replace(/,/g, ' ') // 配列を文字に直してコンマを空白文字に return result; }

今回は何も見ずにかけたんですが、、、最初のアルファベットの配列とか絶対無駄なように見えます。でもアルファベットの順番を取り出すメソッドなんて知らないし。。

Best Practice #1 の回答

function alphabetPosition(text) { return text .toUpperCase() .match(/[a-z]/gi) .map( (c) => c.charCodeAt() - 64) .join(' '); }

やっぱりアルファベットの配列なんて不要でしたね。return に直接書いていますが改行されていて読みやすいですね。

  1. toUpperCase() : 大文字に変換
  2. match(/[a-z]/gi) :
    match はマッチした文字を配列に入れるので、ここで全ての文字をいれた配列を作れるのですね。
    regex の gii が大事で、小文字と大文字の両方にマッチさせることができます。
    でも、せっかく1で大文字に変換したので、 match(/[A-Z]/g) でもいいのでは?
  3. map( (c) => c.charCodeAt() - 64) :
    String.prototype.charCodeAt(index) は、index 位置の文字の UTF-16 で表される数値を返してくれるメソッド。UTF-16 の一覧によれば、大文字のアルファベットは 65 番目から始まるので、64 を引いているんですね👀
  4. join(' '):
    join() は Array を String に変換した文字列を返すメソッドですが、引数に空文字をいれれば、各配列の要素の間にスペースが開くというわけです。
    私の回答の join().replace(/,/g, ' ')join(' ') だけで書けるのに無駄なことをしてました。

しかしこの回答は文字以外の、記号などのみの場合、エラーになってしまうので今はテストが通らないようです。
記号の場合も通らせる場合、

function alphabetPosition5(text) { return (text.toUpperCase().match(/[A-Z]/g) || []) .map( (c) => c.charCodeAt() - 64) .join(' '); }

のようにして空配列を渡す書き方がコメントにありました。スマートですね。可読性はちょっと下がるかもしれないですが、この書き方も勉強になりました。

Best Practice #2 の回答

function alphabetPosition(text) { var result = ""; for (var i = 0; i < text.length; i++){ var code = text.toUpperCase().charCodeAt(i) if (code > 64 && code < 91) result += (code - 64) + " "; } return result.slice(0, result.length-1); }

自分の回答と #1 の回答をかけ合わせた感じですね。 配列ではなく文字列に足していくやりかたです。
人のコードを読むと勉強になるし、自分のループの中にループ入れる書き方を直していきたいと思った日でした。