简体   繁体   English

在与 ES6 深度嵌套的对象的 javascript 数组中查找值

[英]Find value in javascript array of objects deeply nested with ES6

In an array of objects I need to find a value -- where key is activity : However the activity key can be deeply nested in the array like so:在对象数组中,我需要找到一个value ——其中keyactivity :但是activity key可以像这样深入嵌套在数组中:

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',
                    },
                ],
            },
        ],    
    },
    {} ...
    {} ...
];

So I wrote a recursive algorithm to find out if a certain activity is in the array:所以我写了一个递归算法来找出某个活动是否在数组中:

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;
};

Is there an ES6 way of determining if an activity exists in an array like this?是否有ES6方法来确定活动是否存在于这样的数组中?

I tried something like this:我试过这样的事情:

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

But this won't work with deeply nested activities.但这不适用于深度嵌套的活动。

Thanks谢谢

You can use some() method and recursion to find if activity exists on any level and return true/false as result.您可以使用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'))

While not as elegant as a recursive algorithm, you could JSON.stringify() the array, which gives this:虽然不像递归算法那么优雅,但你可以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"}]}]}]

You could then use a template literal to search for the pattern:然后,您可以使用模板文字来搜索模式:

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

Complete function:功能齐全:

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

First, your function could be improved by halting once a match is found via the recursive call.首先,一旦通过递归调用找到匹配项,就可以通过暂停来改进您的功能。 Also, you're both declaring match outside, as well as returning it.此外,你们都在外面声明match ,并返回它。 Probably better to just return.可能更好地返回。

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;
};

There's no built in deep search, but you can use .find with a named function if you wish.没有内置的深度搜索,但如果您愿意,可以将.find与命名函数一起使用。

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

We now use object-scan for simple data processing tasks like this.我们现在使用对象扫描来完成这样的简单数据处理任务。 It's really good once you wrap your head around how to use it.一旦你了解如何使用它,这真的很好。 Here is how one could answer your questions这是人们如何回答您的问题

 // const objectScan = require('object-scan'); const find = (activity, input) => objectScan(['**'], { abort: true, rtn: 'value', filterFn: ({ value }) => value.activity === activity })(input); 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"}]}]}] console.log(find('scuba diving', activityItems)); // => { name: 'Beach', activity: 'scuba diving' }
 .as-console-wrapper {max-height: 100% !important; top: 0}
 <script src="https://bundle.run/object-scan@13.8.0"></script>

Disclaimer : I'm the author of object-scan免责声明:我是对象扫描的作者

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM