Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

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?

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

like image 738
user2456977 Avatar asked Sep 20 '17 18:09

user2456977


2 Answers

You can use some() method and recursion to find if activity exists on any level and return true/false as result.

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'))
like image 60
Nenad Vracar Avatar answered Sep 27 '22 16:09

Nenad Vracar


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/[email protected]"></script>

Disclaimer: I'm the author of object-scan

like image 28
vincent Avatar answered Sep 27 '22 16:09

vincent