web-dev-qa-db-ja.com

ES6で深くネストされたオブジェクトのJavaScript配列で値を見つける

オブジェクトの配列でvalueを見つける必要があります--keyactivityです。ただし、activitykeyは深くすることができます次のように配列にネスト:

const activityItems = [
    {
        name: 'Sunday',
        items: [
            {
                name: 'Gym',
                activity: 'weights',
            },
        ],
    },
    {
        name: 'Monday',
        items: [
            {
                name: 'Track',
                activity: 'race',
            },
            {
                name: 'Work',
                activity: 'meeting',
            },
            {
                name: 'Swim',
                items: [
                    {
                        name: 'Beach',
                        activity: 'scuba diving',
                    },
                    {
                        name: 'Pool',
                        activity: 'back stroke',
                    },
                ],
            },
        ],    
    },
    {} ...
    {} ...
];

そのため、特定のアクティビティーが配列内にあるかどうかを確認するための再帰アルゴリズムを作成しました。

let match = false;
const findMatchRecursion = (activity, activityItems) => {
    for (let i = 0; i < activityItems.length; i += 1) {
        if (activityItems[i].activity === activity) {
            match = true;
            break;
        }

        if (activityItems[i].items) {
            findMatchRecursion(activity, activityItems[i].items);
        }
    }

    return match;
};

ES6このような配列にアクティビティが存在するかどうかを判断する方法は?

私はこのようなものを試しました:

const findMatch(activity, activityItems) {
    let obj = activityItems.find(o => o.items.activity === activity);
    return obj;
}

しかし、これは深くネストされたアクティビティでは機能しません。

ありがとう

7
user2456977

some()メソッドと再帰を使用して、アクティビティが任意のレベルに存在するかどうかを確認し、結果としてtrue/falseを返すことができます。

const activityItems = [{"name":"Sunday","items":[{"name":"Gym","activity":"weights"}]},{"name":"Monday","items":[{"name":"Track","activity":"race"},{"name":"Work","activity":"meeting"},{"name":"Swim","items":[{"name":"Beach","activity":"scuba diving"},{"name":"Pool","activity":"back stroke"}]}]}]

let findDeep = function(data, activity) {
  return data.some(function(e) {
    if(e.activity == activity) return true;
    else if(e.items) return findDeep(e.items, activity)
  })
}

console.log(findDeep(activityItems, 'scuba diving'))
5
Nenad Vracar

再帰的なアルゴリズムほどエレガントではありませんが、配列をJSON.stringify()すると、次のようになります。

[{"name":"Sunday","items":[{"name":"Gym","activity":"weights"}]},{"name":"Monday","items":[{"name":"Track","activity":"race"},{"name":"Work","activity":"meeting"},{"name":"Swim","items":[{"name":"Beach","activity":"scuba diving"},{"name":"Pool","activity":"back stroke"}]}]}]

次に template literal を使用してパターンを検索できます。

`"activity":"${activity}"`

完全な機能:

findMatch = (activity, activityItems) =>
  JSON.stringify(activityItems).includes(`"activity":"${activity}"`);
const activityItems = [{
    name: 'Sunday',
    items: [{
      name: 'Gym',
      activity: 'weights',
    }, ],
  },
  {
    name: 'Monday',
    items: [{
        name: 'Track',
        activity: 'race',
      },
      {
        name: 'Work',
        activity: 'meeting',
      },
      {
        name: 'Swim',
        items: [{
            name: 'Beach',
            activity: 'scuba diving',
          },
          {
            name: 'Pool',
            activity: 'back stroke',
          },
        ],
      },
    ],
  }
];

findMatch = (activity, activityItems) =>
  JSON.stringify(activityItems).includes(`"activity":"${activity}"`);

console.log(findMatch('scuba diving', activityItems)); //true
console.log(findMatch('dumpster diving', activityItems)); //false
4
Rick Hitchcock

まず、再帰呼び出しで一致が見つかったら停止することにより、関数を改善できます。また、あなたは両方ともmatchを外部で宣言し、それを返します。たぶん戻るだけのほうがいいでしょう。

const findMatchRecursion = (activity, activityItems) => {
    for (let i = 0; i < activityItems.length; i += 1) {
        if (activityItems[i].activity === activity) {
            return true;
        }

        if (activityItems[i].items && findMatchRecursion(activity, activityItems[i].items) {
            return true;
        }
    }

    return false;
};

組み込みのディープ検索はありませんが、.find必要に応じて、名前付き関数を使用します。

var result = !!activityItems.find(function fn(item) {
  return item.activity === "Gym" || (item.items && item.items.find(fn));
});
1
llama