JavaScriptで文字列が同一の部分文字列の繰り返しかどうかを判定する方法
この記事では、引数として渡された文字列が同一の部分文字列の繰り返しのみで構成されているかを判定し、true または false を返す JavaScript 関数の作り方を解説します。
条件として、入力文字列の長さは必ず 1 より大きく、部分文字列は少なくとも 2 回以上繰り返されていなければなりません。
判定結果の例
'aa'→true:「a」が 2 回繰り返されているため'aaa'→true:「a」が 3 回繰り返されているため'abcabcabc'→true:「abc」が 3 回繰り返されているため'aba'→false:同一の部分文字列が 2 回以上続いていないため'ababa'→false:「ab」は 2 回現れますが、余分な「a」が残ってしまうため
実装コード(再帰を使う方法)
const checkCombination = (str = '') => {
if (str.length === 1) {
return true;
}
for (let i = 1; i <= str.length / 2; i++) {
// 全体の長さが i で割り切れない候補はスキップ
if (str.length % i !== 0) {
continue;
}
const sub = str.substring(0, i);
if (isRepeating(sub, str)) {
return true;
}
}
return false;
};
const isRepeating = (sub, str) => {
if (str.length > sub.length) {
const left = str.substring(0, sub.length);
const right = str.substring(sub.length);
return left === sub && isRepeating(sub, right);
}
return str === sub;
};
console.log(checkCombination('aa')); // true
console.log(checkCombination('aaa')); // true
console.log(checkCombination('abcabcabc')); // true
console.log(checkCombination('aba')); // false
console.log(checkCombination('ababa')); // false
コードのポイント
checkCombination 関数は、文字列の長さの半分以下の各長さ i について、全体の長さが i で割り切れる場合だけ、先頭から i 文字を候補の部分文字列 sub として切り出します。割り切れない場合は、sub を何度繰り返しても元の長さにならないため、検証する必要がありません。
isRepeating 関数は再帰的に動作します。まず文字列の先頭が sub と一致するかを確認し、一致していれば残りの部分に対して同じチェックを繰り返します。最後まですべて一致すれば、文字列全体が sub の繰り返しであると判定できます。
別解:文字列の連結を使ったシンプルな方法
もっと短く書きたい場合は、「文字列を 2 つ連結し、先頭と末尾の 1 文字を取り除いた中に元の文字列が含まれるか」を確認するテクニックが便利です。
// 文字列を 2 倍に連結し、両端を除いた範囲に元の文字列が含まれるかを判定
const checkCombination = (str = '') => (str + str).slice(1, -1).includes(str);
console.log(checkCombination('abcabc')); // true
console.log(checkCombination('ababa')); // false
これは、文字列 s が周期 p の繰り返しでできているとき、s + s の内部(両端を除いた範囲)には必ず s がもう一度現れるという性質を利用したものです。1 行で書けるため、実務でもよく使われる定番のイディオムです。
出力結果
最初のコードを実行すると、コンソールには次のように表示されます。
true true true false false
-
【JavaScript】ユーザーが入力した文字列が配列に含まれているかチェックする方法
本記事では、ユーザーに文字列を入力してもらうための入力欄を備えたJavaScriptプログラムを作成します。 プログラムは、入力された値が、あらかじめコード内で定義しておいた配列の要素と一致するかどうかを判定します。入力された文字列が配列内に存在すれば画面に「true」を、存在しなければ「false」を表示します。 実装例 この動作を実現するコードは以下のとおりです。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> &nb
-
JavaScriptで不正な時間文字列(HH:MM:SS)を正規化して修正する方法
JavaScriptでは、「HH:MM:SS」形式の時間文字列を扱う場面がよくあります。しかし、時間の加算処理などで計算ミスが発生すると、分や秒が60を超えてしまう「壊れた」時間文字列が生成されることがあります。この記事では、そうした不正な時間文字列を正しく正規化する方法を解説します。 課題:壊れた時間文字列とは 今回求められるのは、JavaScriptで「HH:MM:SS」形式の時間文字列を受け取り、必要な修正を加えた上で、正しい時間文字列として返す関数を作成することです。 問題になるのは、加算処理のバグによって、次のような不正な値が含まれてしまうケースです。 MM(分)の部分が60を超え