JavaScriptで無限に繰り返し拡張される文字列から部分文字列を取得する方法
問題の概要
今回作成するのは、次の3つの引数を受け取るJavaScript関数です。
- 第1引数:元となる文字列
- 第2引数:開始インデックス
- 第3引数:終了インデックス
関数は、第1引数の文字列が自分自身を末尾に何度も連結され、無限に伸びていくものと仮定したうえで、開始インデックスから終了インデックスまでの範囲に含まれる部分文字列を返します。
たとえば、入力が次の場合を考えてみましょう。
const str = 'helloo'; const start = 12; const end = 15;
「helloo」が helloohelloohelloo… のように永遠に続くとすると、インデックス12〜14に対応する文字は「hel」になります。つまり、期待される出力は次のとおりです。
const output = 'hel';
アプローチ:剰余演算で周期を利用する
ポイントは剰余演算子(%)です。文字列の長さを n とすると、無限に繰り返された文字列の i 番目の文字は、元の文字列の i % n 番目の文字と必ず一致します。この性質を使えば、巨大な文字列を実際に生成しなくても、目的の部分文字列を1文字ずつ組み立てることができます。
シンプルな実装例
const str = 'helloo';
const start = 12;
const end = 15;
const findSubstring = (str = '', start, end) => {
const n = str.length;
let res = '';
// 開始位置から終了位置の直前まで、対応する文字を1文字ずつ取り出す
for (let i = start; i < end; i++) {
res += str[i % n];
}
return res;
};
console.log(findSubstring(str, start, end));
出力
コンソールには次のように表示されます。
hel
処理の流れ
- i = 12 のとき:12 % 6 = 0 → str[0] = 'h'
- i = 13 のとき:13 % 6 = 1 → str[1] = 'e'
- i = 14 のとき:14 % 6 = 2 → str[2] = 'l'
これらを順に連結した「hel」が返り値となります。
範囲が大きい場合の高速な実装
上記のループ方式は理解しやすい反面、start と end の差が非常に大きい場合には1文字ずつの処理になるため非効率です。そんなときは、repeat() で必要な回数だけ文字列を複製してから slice() で切り出す方法が有効です。
const findSubstringFast = (str = '', start, end) => {
const n = str.length;
const s = start % n; // 1周期内における開始位置
const len = end - start; // 必要な文字数
// 必要な長さを覆えるまで文字列を繰り返し、まとめて切り出す
return str.repeat(Math.ceil((s + len) / n)).slice(s, s + len);
};
console.log(findSubstringFast('helloo', 12, 15)); // hel
この方法なら、範囲が数千・数万文字に及ぶ場合でも、ループで1文字ずつ連結するよりもはるかに短時間で結果を得られます。
まとめ
無限に繰り返される文字列から部分文字列を取り出す鍵は、剰余演算によって全体のインデックスを1周期内のインデックスへ変換することです。短い範囲なら単純なループで十分ですが、大きな範囲を扱う場面では repeat() と slice() を組み合わせると効率的です。
-
JavaScriptで文字列に部分文字列が含まれるか判定する方法|search()メソッドの使い方
JavaScriptで部分文字列の存在を確認するには? JavaScriptで「ある文字列の中に特定の部分文字列(サブストリング)が含まれているか」を確認したい場合、Stringオブジェクトのsearch()メソッドを使うのが一般的な方法の一つです。 search()メソッドは、引数に渡した文字列(または正規表現)が対象の文字列内で最初に現れる位置(インデックス)を返します。見つからなかった場合は -1 を返すため、この戻り値を判定条件として使うことで、部分文字列の有無を簡単にチェックできます。 search()メソッドを使ったサンプルコード 次のコードは、文字列「Tutorialspoint
-
JavaScriptで文字列を真偽値(Boolean)に変換する方法
JavaScriptでは、文字列が「true」というリテラルと一致するかどうかを比較演算子で判定することで、文字列を実質的に真偽値(Boolean)として扱うことができます。ここでは、==(緩い等価比較)と===(厳密等価比較)の2つの方法を使った具体例を紹介します。 サンプルコード <!DOCTYPE html> <html> <head> <style> body { font-family: &