Skip to content
Advertisement

Traverse JavaScript array and dynamically find deep nested values

I am currently manually looping through an array and doing deeper and deeper nested loops to compare values, but I am curious if there is any way to do this search automatically? I need to find deep nested arrays, compare 1 or 2 values and then also be able to modify the values.

Example array.

searchableArray = [];

searchableArray.push({id: 3, type: 'some-type', text: 'text', nestedElements: [{id: 4, type: 'some-type', text: 'other text', nestedElements: []}, {id: 5, type: 'another-type',  text: 'more text', nestedElements: []}]})
searchableArray.push({id: 6, type: 'other-type', text: 'text', nestedElements: [{id: 7, type: 'other-type', text: 'other text', nestedElements: []}, {id: 8, type: 'another-type',  text: 'more text', nestedElements: []}]})
searchableArray.push({id: 9, type: 'another-type', text: 'text', nestedElements: [{id: 10, type: 'another-type', text: 'other text', nestedElements: []}, {id: 11, type: 'another-type',  text: 'more text', nestedElements: []}]})

Basically I need to search for id (It will be unique throughout the entire array and object, but could be nested various levels deep inside an object inside another array. But will always be called “nestedElements”.

I need to be able to find the ID and then modify the object that ID belongs too and put it back in the array I am using.

Right now I am just making manual loops for each potential nested array. (Which is a lot of extra copy paste code)

for(var i = 0; i < searchableArray.length; ++i) 
{
    if(searchableArray[i].id == 6) //6 would actually be a variable, just doing a manual example
    {
        if(searchableArray[i].nestedElements.length > 0)
        {
            for(var j = 0; j < searchableArray[i].nestedElements.length; ++j) 
            {
                if(searchableArray[i].nestedElements[j].id == '7')
                {
                    if(searchableArray[i].nestedElements[j].type == 'other-type')
                    {
                        searchableArray[i].nestedElements[j].dosomething = 'do this to something in the object';
                    }
                    else if(searchableArray[i].nestedElements[j].type == 'another-type')
                    {
                        searchableArray[i].nestedElements[j].dosomething = 'do this other thing to the object';
                    }
                }
            }
        }
    }
}

This would get very huge with nested loops for everything, so is there any easier way to do it?

Thanks!

Advertisement

Answer

This is what you want:

const searchableArray = [];

searchableArray.push({ id: 3, type: 'some-type', text: 'text', nestedElements: [{ id: 4, type: 'some-type', text: 'other text', nestedElements: [] }, { id: 5, type: 'another-type', text: 'more text', nestedElements: [] }] })
searchableArray.push({ id: 6, type: 'other-type', text: 'text', nestedElements: [{ id: 7, type: 'other-type', text: 'other text', nestedElements: [] }, { id: 8, type: 'another-type', text: 'more text', nestedElements: [] }] })
searchableArray.push({ id: 9, type: 'another-type', text: 'text', nestedElements: [{ id: 10, type: 'another-type', text: 'other text', nestedElements: [] }, { id: 11, type: 'another-type', text: 'more text', nestedElements: [] }] });

const find = (id, cb) => {
    const ar = searchableArray.slice(0);
    for (var i = 0; i < ar.length; i++) {
        if (ar[i].id === id) {
            return cb(ar[i]);
        }
        if (ar[i].nestedElements.length) {
            ar.push(...ar[i].nestedElements);
        }
    }

}

find(7, (o) => {
    if (o.type == 'other-type') {
        o.dosomething = 'do this to something in the object';
    } else if (o.type == 'another-type') {
        o.dosomething = 'do this other thing to the object';
    }
});

console.log(JSON.stringify(searchableArray));
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement