背景
「codewars」というプログラミング学習サイトが勉強になるなと思い最近少しづつ問題を解いています。
codewarsは他の人の答えを見ることができて、Best Practicesのソースが乗っていて非常に勉強になります。見て終わりももったいないので自分が書いたものとBest Practicesを比較して考察してみたいと思います。
言語はJavaScripを使用しました。
問題
入力として連続する(増加する)文字の配列を受け取り、配列内の欠落文字を返すメソッドを記述します。
常に有効な配列を取得します。そして、それは常に正確に一つの文字が欠落しているでしょう。配列の長さは常に少なくとも2つです。
配列には常に1文字のみが含まれます。
例)
['a','b','c','d','f'] -> 'e'
['O','Q','R','S'] -> 'P'
自分の回答
function findMissingLetter(array)
{
const alphabetList = 'abcdefghijklmnopqrstuvwxyz';
const startIndex = alphabetList.indexOf(array[0].toLowerCase());
let count = 0;
let resultIndex = 0;
for(let i = startIndex; array.length + startIndex > i; i++) {
if(alphabetList[i] !== array[count].toLowerCase()) {
resultIndex = count;
break;
}
count++;
}
if(isUpperCase(array[0])) {
return alphabetList[startIndex + resultIndex].toUpperCase();
}
return alphabetList[startIndex + resultIndex];
}
// 大文字判定
function isUpperCase(str) {
let arr = str.match(/^[A-Z]+$/);
return arr ? true : false;
}
Best Practices
function findMissingLetter(array) {
let first = array[0].charCodeAt(0)
for (let i = 1; i < array.length; i++) {
if (first + i !== array[i].charCodeAt(0)) {
return String.fromCharCode(first + i)
}
}
throw new Error("Invalid input")
}
考察
見てお分かりの通り、私のソースはクソです。
Best Practicesと比べて無駄が多すぎる、、、
この時点で心が折れそうですが続けます。
まずは問題についてですが、入力値はアルファベットがいくつか順番に配列に入っていて、抜けているアルファベットを出力するというもの。
私はまず、アルファベットのリストを作成して、入力値の最初のインデックスを取りました。
const alphabetList = 'abcdefghijklmnopqrstuvwxyz';
const startIndex = alphabetList.indexOf(array[0].toLowerCase());
一方、Best Practicesは以下。
let first = array[0].charCodeAt(0)
charCodeAt、、、?
与えられたインデックス位置の文字の UTF-16 コードユニット値を表す数値。index が範囲外だった場合、NaN。
変数firstには入力値の配列の一番最初のアルファベットのUTF-16 コードユニット値が入っているらしい。
そして?
for (let i = 1; i < array.length; i++) {
if (first + i !== array[i].charCodeAt(0)) {
return String.fromCharCode(first + i)
}
}
for文の中でfirst + i
とすることで次のアルファベットを取得する。
そして、array[i].charCodeAt(0)
で入力値の配列と比較する。
入力値と異なっていた場合は以下の処理となる。
return String.fromCharCode(first + i)
String.fromCharCode、、、?
String.fromCharCode() 静的メソッドは、指定された UTF-16 コードユニットのシーケンスから生成された文字列を返します。
これで文字コードから文字列に変換している訳ですね。
まとめ
charCodeAtとfromCharCodeをうまく利用しているようでした。
確かにこれで大文字小文字の判定とかいらないし、いちいちアルファベットのリストとか作成しなくてもよくなる。