【JavaScript】文字列内の特定の部分文字列を
タグで囲む方法
問題の概要
本記事では、第1引数として文字列 str を、第2引数として文字列の配列 arr を受け取るJavaScript関数を作成します。この関数の目的は、str の中に含まれていて、かつ arr にも存在する部分文字列を、開始タグ <p> と終了タグ </p> のペアで囲むことです。
この問題には、次の2つの重要なルールがあります。
- 重なりの扱い: 2つの部分文字列が重なり合っている場合、それらを1組の段落タグだけでまとめて囲む必要があります。
- 連続部分の結合: 段落タグで囲まれた2つの部分が隣接して連続している場合も、それらを結合して1つのブロックとして扱います。
具体例
たとえば、入力文字列と配列が次のような場合を考えてみましょう。
const str = 'kkkllmm'; const arr = ["kkk","kkl","lm"];
このとき、期待される出力は次のとおりです。
const output = '<p>kkkllm</p>m';
「kkk」「kkl」「lm」の3つの部分文字列は互いに重なり合っているため、<p>kkkllm</p> とひとまとめに囲まれ、末尾の「m」だけがタグの外側に残ります。
実装コード
この要件を満たすコードは以下のとおりです。
const str = 'kkkllmm';
const arr = ["kkk","kkl","lm"];
var addParagraphTag = (str = [], arr = []) => {
if(!arr.length){
return str
};
const { length } = str;
let paraBoolean = new Array(length).fill(false);
let end = 0;
for (let i = 0; i < length; i++){
for (let j = 0; j < arr.length; j++){
let word = arr[j];
if (str.startsWith(word,i)) {
end = Math.max(end, i + word.length);
};
}
paraBoolean[i] = end > i;
};
let curr = 0;
let newStr = '';
while (curr < length) {
while(paraBoolean[curr] === false) {
newStr += str[curr++];
}
if (curr >= length) break;
newStr += '<p>';
let startBold = curr;
while (paraBoolean[curr] === true) curr++;
newStr += str.slice(startBold, curr);
newStr += '</p>';
};
return newStr;
};
console.log(addParagraphTag(str, arr));
コードの解説
このアルゴリズムのポイントは以下の4点です。
- 早期リターン: 配列
arrが空の場合は処理が不要なため、元の文字列をそのまま返します。 - ブール配列によるマーキング: 文字列と同じ長さの
paraBoolean配列を用意し、各位置がタグで囲む対象の範囲内にあるかどうかを記録します。 - startsWithによる前方一致判定: 各位置
iについて、配列内の各単語がその位置から始まるかどうかを確認し、一致すればendをi + word.lengthの最大値まで更新します。これにより、重なる部分文字列も自動的に1つの連続した区間として扱われます。 - 区間ごとのタグ付与: 最後に文字列全体を走査し、
trueが連続する区間を検出するたびに、その範囲を<p>〜</p>で囲んで結果文字列へ追加していきます。
出力結果
コンソールに出力される結果は次のとおりです。
<p>kkkllm</p>m
-
JavaScriptで循環するアルファベット文字列に含まれる一意な部分文字列を数える方法
問題概要文字列 abcdefghijklmnopqrstuvwxyz を無限に繰り返してできる循環文字列 S を考えてみましょう。このとき、S は次のような形になります。...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd.....今回実装するのは、引数として文字列 str を1つだけ受け取る JavaScript 関数です。この関数は以下の処理を行います。str の空でない部分文字列のうち、S に含まれるものをすべて洗い出す。S 内に存在する str の異なる非空部分文字列の個数を最終的な結果として返す。たとえば、関数への入
-
【JavaScript】文字列が同一部分文字列の繰り返しで構成されているか判定する方法
問題概要文字列を1つだけ引数として受け取り、その文字列が「ある部分文字列を複数回連結したもの」になっているかどうかを判定するJavaScript関数を実装します。たとえば、関数への入力が次の場合:const str = 'thisthisthisthis';期待される出力は以下のとおりです。const output = true;出力の説明この文字列は「this」という部分文字列を4回繰り返して構成されているため、true が返されます。実装コードこの問題を解くコードは次のようになります。const str = 'thisthisthisthis';const