【JavaScript】文字列が配列内の文字列の組み合わせで構成できるか判定する方法
概要
本稿では、第1引数に文字列の配列、第2引数に判定対象の文字列を受け取るJavaScript関数を作成します。この関数は、第2引数の文字列が、配列内の文字列を任意の順序で組み合わせることで完全に構成できる場合に true を返すものです。
まず、具体的な例を見てみましょう。入力となる配列が次の通りです。
const arr = ['for', 'car', 'keys', 'forth'];
そして、判定対象の文字列がこちらです。
const str = 'forthcarkeys';
この場合、出力は true になります。「forthcarkeys」という文字列は、配列のインデックス3の「forth」、インデックス1の「car」、インデックス2の「keys」を連結したものと一致するためです。
サンプルコード
実装の流れは大きく分けて2段階です。まず indexOf() を使って、配列内の各文字列が対象文字列のどの位置に出現するかをすべて洗い出します。続いて再帰処理により、各候補を「使う/使わない」のパターンで全探索し、文字列を余りなく埋め尽くせる組み合わせが存在するかを確認します。
const arr = ['for', 'car', 'keys', 'forth'];
const str = 'forthcarkeys';
const checkPossibility = (str = '', arr = []) => {
// 配列内の各文字列が対象文字列に出現する位置をすべて収集する
let possibilities = arr.reduce(function (r, a) {
let p = str.indexOf(a);
while (p !== -1) {
r.push({ word: a, position: p });
p = str.indexOf(a, p + 1);
}
return r;
}, []);
// 再帰的に「単語を使う/使わない」パターンを全探索する
const findRecursively = (i, t) => {
let s = t.slice();
// 候補をすべて検討し終えたら、未使用の文字が残っていないか確認
if (i === possibilities.length) {
return !t.join('');
}
// 単語を置こうとする位置の文字がすべて未使用であれば、使用済みとしてマーク
if (possibilities[i].word.split('').every(function (c, j) {
return s[j + possibilities[i].position] !== '';
})) {
for (let j = 0; j < possibilities[i].word.length; j++) {
s[j + possibilities[i].position] = '';
}
// この単語を採用したケースを試す
if (findRecursively(i + 1, s)) {
return true;
}
}
// この単語を採用しなかったケースも試す
return findRecursively(i + 1, t);
};
return findRecursively(0, str.split(''));
};
console.log(checkPossibility(str, arr));
実行結果
コンソールには以下のように表示されます。
true
処理のポイント
- 候補の収集:
reduce()とindexOf()を組み合わせ、各文字列が対象文字列内に出現するすべての位置を記録します。 - 再帰による全探索: 各候補ごとに「採用する」「採用しない」の2通りを再帰的に試行し、成功する組み合わせが1つでも見つかれば
trueを返します。 - 文字の二重使用を防止: 採用した単語に該当する部分は空文字でマークされるため、同じ位置の文字が別の単語に再利用されることはありません。
-
【JavaScript】ユーザーが入力した文字列が配列に含まれているかチェックする方法
本記事では、ユーザーに文字列を入力してもらうための入力欄を備えたJavaScriptプログラムを作成します。 プログラムは、入力された値が、あらかじめコード内で定義しておいた配列の要素と一致するかどうかを判定します。入力された文字列が配列内に存在すれば画面に「true」を、存在しなければ「false」を表示します。 実装例 この動作を実現するコードは以下のとおりです。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> &nb
-
JavaScriptで文字列の二次元配列をソートして対角要素を見つける方法
本記事では、文字列の配列を扱うJavaScriptのアルゴリズム問題を解説します。「配列をアルファベット順にソートした後、対角線上の文字を抽出する」というシンプルながら応用範囲の広いテクニックを、サンプルコードとともにわかりやすく紹介します。 問題 n個の文字列を要素として持つ配列を受け取るJavaScript関数を作成します。ここで、配列内の各文字列はすべてちょうどn文字で構成されているものとします。つまり、この配列はn×nの正方行列として扱うことができます。 関数には以下の2つの処理が求められます。 まず、配列をアルファベット順(辞書順)にソートすること 次に、ソート後の配列を行列とみな