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
に直接書いていますが改行されていて読みやすいですね。
toUpperCase()
: 大文字に変換match(/[a-z]/gi)
:
match
はマッチした文字を配列に入れるので、ここで全ての文字をいれた配列を作れるのですね。
regex のgi
のi
が大事で、小文字と大文字の両方にマッチさせることができます。
でも、せっかく1で大文字に変換したので、match(/[A-Z]/g)
でもいいのでは?map( (c) => c.charCodeAt() - 64)
:
String.prototype.charCodeAt(index)
は、index 位置の文字の UTF-16 で表される数値を返してくれるメソッド。UTF-16 の一覧によれば、大文字のアルファベットは 65 番目から始まるので、64 を引いているんですね👀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 の回答をかけ合わせた感じですね。
配列ではなく文字列に足していくやりかたです。
人のコードを読むと勉強になるし、自分のループの中にループ入れる書き方を直していきたいと思った日でした。