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

JavaScriptの再帰関数でネストされたオブジェクトのキーを検索して値を取得する方法

JavaScriptでは、プロパティの値としてさらに別のオブジェクトを持つ、入れ子(ネスト)構造のオブジェクトを扱うことがよくあります。ネストは2〜3階層程度のこともあれば、それ以上に深くなるケースもあります。

サンプルオブジェクト

以下のようなオブジェクトを例に考えてみましょう。

const people = {
    Ram: {
        fullName: 'Ram Kumar',
        details: {
            age: 31,
            isEmployed: true
        }
    },
    Sourav: {
        fullName: 'Sourav Singh',
        details: {
            age: 22,
            isEmployed: false
        }
    },
    Jay: {
        fullName: 'Jay Grewal',
        details: {
            age: 26,
            isEmployed: true
        }
    }
}

実現したいこと

今回の課題は、「オブジェクトと文字列を受け取り、その文字列と一致するキーをオブジェクト全体から検索し、一致したすべてのキーの値を配列として返す関数」を作成することです。

この関数を recursiveSearch() と呼びます。オブジェクトが何階層にネストしているか事前に分からないため、再帰処理を使うのが最も自然で適切なアプローチとなります。

recursiveSearch() の完全なコード

const people = {
    Ram: {
        fullName: 'Ram Kumar',
        details: {
            age: 31,
            isEmployed: true
        }
    },
    Sourav: {
        fullName: 'Sourav Singh',
        details: {
            age: 22,
            isEmployed: false
        }
    },
    Jay: {
        fullName: 'Jay Grewal',
        details: {
            age: 26,
            isEmployed: true
        }
    }
};

const recursiveSearch = (obj, searchKey, results = []) => {
    const r = results;
    Object.keys(obj).forEach(key => {
        const value = obj[key];
        if(key === searchKey && typeof value !== 'object'){
            r.push(value);
        }else if(typeof value === 'object'){
            recursiveSearch(value, searchKey, r);
        }
    });
    return r;
};

console.log(recursiveSearch(people, 'age'));

コードの解説

この関数の動作は以下の流れになっています。

まず Object.keys() でメインオブジェクトのキーを順番に取り出しながら走査を行います。プロパティの値がオブジェクトだった場合は、そこで処理を終えずに、そのサブオブジェクトに対して同じ recursiveSearch() を再帰的に呼び出します。これにより、どれだけ深くネストしていてもすべての階層を網羅的にチェックできます。

一方、キーが検索対象の文字列と一致し、かつ値がオブジェクトではない場合は、その値をすぐに results 配列に記録します。最後にすべての走査が完了した時点で、見つかった値が格納された results 配列を返します。

なお、results をデフォルト引数として受け渡すことで、再帰呼び出しの間でも同一の配列を共有できるのがポイントです。

計算量について

この関数の時間計算量は O(mn) です。ここで n はメインオブジェクト内の子オブジェクトの数、m はネストの最深階層を表します。

実行結果

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

[ 31, 22, 26 ]
  1. 【JavaScript】配列内のネストされたオブジェクトの値を合計する方法

    この記事では、JavaScriptを使って、配列内にネストされた(入れ子構造の)オブジェクトの値を合計する方法を解説します。サンプルコードでは、JSONデータの複数階層に格納された数値(costNum)を順番に取り出し、その合計をブラウザ上に表示します。 コード例 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=d

  2. JavaScriptのObject.keys().map()とArray.map()の違いを徹底解説

    JavaScriptにおいて、Array.map()は配列の各要素に関数を適用し、その結果を新しい配列として返すメソッドです。一方、オブジェクトには直接map()メソッドが用意されていないため、Object.keys().map()という形で、まずObject.keys()を使ってオブジェクトのキーを配列として取得し、そこにmap()を適用するのが一般的なテクニックとなります。 この記事では、両者の使い方の違いを、実際に動作するサンプルコードと実行結果をもとにわかりやすく解説します。 サンプルコード 以下は、Object.keys().map()とArray.map()の動作を比較できるJa