JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

【JavaScript】ドット区切りの文字列を再帰的に解析してオブジェクトに変換する方法

概要

文字列の配列を受け取り、それぞれの文字列を解析して対応するネスト構造のオブジェクトを返すJavaScript関数を作成する方法を解説します。ドット区切りのパス形式データを扱う際に役立つテクニックです。

要件の確認

たとえば、次のような配列が入力として与えられたとします。

const arr = [
    "country.UK.level.1",
    "country.UK.level.2",
    "country.US.level.1",
    "country.UK.level.3"
];

この場合、期待される出力は以下のようになります。

const output = {
    "country": [
        {"UK" : {"level" : ["1", "2", "3"]}},
        {"US" : {"level" : ["1","2"]}}
    ]
}

条件

この問題には、次の3つの条件が課されています。

  • 入力は未ソートでも動作すること:str 配列内の文字列は必ずしもソートされていないため、どんな順序の入力にも対応できる堅牢な実装が必要です。
  • x.y.x.y 形式のパターンに従うこと:文字列は x.y.x.y… というパターンで構成されます。x は配列内で固定の値(例では country や level)、y は変化しうる値(例では UK や 1)です。
  • 再帰的なアプローチを採用すること:文字列の長さ(階層の深さ)は任意のため、ネストの深さに左右されない処理が必要です。文字列が長くなるほど、生成されるオブジェクトのネストも深くなります。

実装コード

以下が、上記の要件を満たすコード例です。

const arr = [
    "country.UK.level.1",
    "country.UK.level.2",
    "country.US.level.1",
    "country.UK.level.3"
];
const stringToObject = arr => {
    const obj = {};
    arr.forEach(str => {
        let curr = obj;
        let splitted = str.split('.');
        let last = splitted.pop();
        let beforeLast = splitted.pop();
        splitted.forEach( sub => {
            if(!curr.hasOwnProperty(sub)){
                curr[sub] = {};
            };
            curr = curr[sub];
        });
        if(!curr[beforeLast]){
            curr[beforeLast] = [];
        };
        curr[beforeLast].push(last);
    });
    return obj;
};
console.log(JSON.stringify(stringToObject(arr), undefined, 4));

実行結果

このコードをコンソールで実行すると、次の出力が得られます。

{
    "country": {
        "UK": {
            "level": [
                "1",
                "2",
                "3"
            ]
        },
        "US": {
            "level": [
                "1"
            ]
        }
    }
}

コードの解説

処理の流れを順番に見ていきましょう。

  1. 文字列の分割:split('.') でドット区切りの文字列を配列に分割します。たとえば "country.UK.level.1" は ["country", "UK", "level", "1"] になります。
  2. 末端要素の取り出し:pop() を2回呼び出し、末尾の要素 last(配列に格納する値)と、その手前の要素 beforeLast(配列のキーとなる部分)を取得します。
  3. ネスト構造の構築:残りの要素については、hasOwnProperty() で既存プロパティの有無を確認しながら空オブジェクトを順に生成し、curr 変数を一段ずつ深い階層へ移動させていきます。
  4. 値の格納:最終的な階層で beforeLast をキーとする配列を用意し、そこへ last を push します。これにより、同じパスを持つ複数の値が1つの配列にまとまります。

この実装のポイントは、ループ内で参照先のオブジェクトを付け替えていくことで、階層の深さがどれほどであっても柔軟に対応できる点です。入力の順序に依存しないため、未ソートのデータでも正しく1つのオブジェクトへ集約できます。

  1. 文字列を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

  2. JavaScriptで配列の配列をオブジェクトに変換する方法

    はじめにJavaScriptでは、「キーと値のペア」を格納した配列の配列(ネストされた配列)を、扱いやすいオブジェクトへ変換したい場面がよくあります。本記事では、その具体的な実装方法をわかりやすく解説します。例として、あるクリケット選手の成績データを表す次のような配列の配列を想定してみましょう。const arr = [     [Name, V Kohli],     [Matches, 13],     [Runs, 590],    &nb