JavaScriptで文字列を階層オブジェクトに変換する方法
文字列から階層的なオブジェクトを作る
JavaScriptでは、2文字ずつのペアで構成された特殊な文字列を、ネスト(入れ子)構造のオブジェクトへ変換したいケースがあります。例えば、次のような文字列を考えてみましょう。
const str = "AABBCCDDEE";
この文字列をもとに、以下のような階層構造を持つオブジェクトを作成することを目標とします。
const obj = {
code: "AA",
sub: {
code: "BB",
sub: {
code: "CC",
sub: {
code: "DD",
sub: {
code: "EE",
sub: {}
}
}
}
}
};
ポイント
このオブジェクトの特徴は以下の通りです。
- 文字列中の各ペア(2文字)ごとに、新しい
subオブジェクトが生成される - 各階層の
codeプロパティは、その階層に対応するペアを表す - 最後のペアの
subは空のオブジェクト{}となる
解決アプローチ:ループによる参照の付け替え
この問題は再帰処理でも解けますが、ここではよりシンプルな「参照を使った反復処理」のアプローチを紹介します。仕組みは以下の通りです。
- 結果を格納する空のオブジェクト
resを作成し、作業用の参照変数refに代入する - 文字列の先頭から2文字を取り出し、
ref.codeに設定する ref.subに新しい空のオブジェクトを作成し、refをその新しいオブジェクトへ付け替える- 文字列が空になるまで繰り返す
ref = ref.sub という参照の付け替えにより、毎回深い階層へ潜り込んでいくのがこのコードのミソです。再帰関数を書かなくても、whileループだけで同様のネスト構造を実現できます。
実装コード
実際のコードは以下のようになります。
const str = "AABBCCDDEE";
const constructObject = str => {
const res = {};
let ref = res;
while (str) {
// 先頭から2文字を取り出す
const words = str.substring(0, 2);
// 残りの文字列を更新
str = str.substring(2);
ref.code = words;
ref.sub = {};
// 参照を1階層深く移動
ref = ref.sub;
}
return res;
};
console.log(JSON.stringify(constructObject(str), undefined, 4));
なお、元のコードで使われていた substr() は非推奨(deprecated)となっているため、上記のコードでは標準的な substring() や slice() を使うことをおすすめします。
実行結果
コンソールには次のように出力されます。
{
"code": "AA",
"sub": {
"code": "BB",
"sub": {
"code": "CC",
"sub": {
"code": "DD",
"sub": {
"code": "EE",
"sub": {}
}
}
}
}
}
まとめ
このように、「結果オブジェクトへの参照を保持しながらループで階層を掘り下げていく」テクニックを使えば、文字列から簡単にネスト構造のオブジェクトを生成できます。ツリー構造のデータ構築や、連結リスト的なデータ生成にも応用できる汎用的なパターンなので、ぜひ覚えておきましょう。
-
JavaScriptで文字列を真偽値(Boolean)に変換する方法
JavaScriptでは、文字列が「true」というリテラルと一致するかどうかを比較演算子で判定することで、文字列を実質的に真偽値(Boolean)として扱うことができます。ここでは、==(緩い等価比較)と===(厳密等価比較)の2つの方法を使った具体例を紹介します。 サンプルコード <!DOCTYPE html> <html> <head> <style> body { font-family: &
-
文字列をJavaScriptオブジェクトに変換する方法【JSON.parse()の使い方】
JavaScriptでJSON形式の文字列をオブジェクトに変換するには、JSON.parse()メソッドを使用します。このメソッドは、引数に渡された文字列を解析(パース)し、対応するJavaScriptオブジェクトを返します。 サンプルコード <!DOCTYPE html> <html lang=ja> <head> <meta charset=UTF-8 /> <meta name=viewport content=width=device-width, initial-scale=1.0 /> <title>Docum