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

JavaScriptでネストされたオブジェクト内の重複値をすべて検出して一覧表示する方法

ネストされた(入れ子構造の)オブジェクトの中に、ペットに関するデータが格納されているとしましょう。以下のようなオブジェクトです。

const pets = {
    owner1: 'Frank',
    owner2: 'Curly',
    owner3: 'Maurice',
    dogs: {
        terriers: {
            name1: 'Fido',
            name2: 'Woofy',
            name3: {
                goodDog: 'Frank',
                badDog: 'Judas',
            }
        },
        poodles: {
            name1: 'Curly',
            name2: 'Fido',
        },
    },
};

私たちの課題は、このようなオブジェクトを引数として受け取るJavaScript関数を作成することです。

この関数は、オブジェクト内のあらゆる階層に存在する重複した値を検索し、見つかった重複値をすべて含む配列を返す必要があります。

上記のオブジェクトの場合、期待される出力は次のとおりです。

const output = ['Frank', 'Curly', 'Fido'];

実装例

実際のコードは以下のとおりです。

const pets = {
    owner1: 'Frank',
    owner2: 'Curly',
    owner3: 'Maurice',
    dogs: {
        terriers: {
            name1: 'Fido',
            name2: 'Woofy',
            name3: {
                goodDog: 'Frank',
                badDog: 'Judas',
            }
        },
        poodles: {
            name1: 'Curly',
            name2: 'Fido',
        },
    },
};

const recursiveSearch = (obj, map = {}, res = []) => {
    Object.keys(obj).forEach(key => {
        if(typeof obj[key] === "object"){
            return recursiveSearch(obj[key], map, res);
        };
        map[obj[key]] = (map[obj[key]] || 0) + 1;
        if(map[obj[key]] === 2){
            res.push(obj[key]);
        }
    });
    return res;
};

console.log(recursiveSearch(pets));

出力結果

コンソールには次のように表示されます。

[ 'Frank', 'Curly', 'Fido' ]

コードの解説

このソリューションのポイントは、再帰処理を使ってネストされたオブジェクト全体を走査している点です。仕組みを順番に見ていきましょう。

1. 再帰による階層の探索

各プロパティの値の型を typeof でチェックし、値がオブジェクトだった場合は、そのオブジェクトに対して自分自身(recursiveSearch)を再度呼び出します。これにより、どれほど深く入れ子になったオブジェクトでも、すべての末端の値にたどり着くことができます。

2. マップによる出現回数の記録

値がプリミティブ型(文字列など)であれば、map オブジェクトにその値の出現回数を記録していきます。map[obj[key]] || 0 の部分は、まだ記録されていない値の場合に0を初期値として使うテクニックです。

3. 重複の検出タイミング

ある値のカウントがちょうど「2」になった時点で、その値を結果配列 res にプッシュします。この条件により、同じ値が3回以上出現しても、結果には一度だけ登録されるようになっています。

なお、この関数は配列も typeof では "object" と判定されるため、配列が含まれるオブジェクトにもそのまま対応できます。また、値が数値や真偽値の場合でも同様に動作しますが、オブジェクトキーへの変換時に文字列化される点には注意が必要です。

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

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

  2. JavaScriptでオブジェクトの値を動的に設定する方法をわかりやすく解説

    JavaScriptでは、オブジェクトのプロパティ(値)を後から動的に変更・設定することができます。本記事では、ボタンをクリックしたタイミングでオブジェクトの値を書き換える具体的なコード例を紹介します。 実装例:オブジェクトの値を動的に変更する 以下のコードでは、student オブジェクトの name プロパティと age プロパティを、ボタンクリック時に動的に更新しています。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" />