简体   繁体   中英

Searching deeply nested object array for a single key

I am trying to search through a deeply nested array and find if a key exists anywhere inside. I have written up a piece of code which does the traversal, but because it is not recursive (only self calling) it cannot return whether or not it has found anything. It just returns undefined since it reaches the end of the function on one of passes.

I was wondering if there was a way I could do this which would allow me to return true on the first occurrence of a specific key.

Here is a JS bin of what I have been working with so far:

https://jsbin.com/qaxuwajuso/edit?js,console

And here is a direct paste of the code from the above example:

function traverse(item, key) {
    if (typeof item === 'object' && !Array.isArray(item) && item !== null) {
        // Object
        for (let itemKey in item) {
            if (itemKey === key) {
                // Is it possible to return true and break out of the function here?
                console.log('found the key: ' + itemKey + ' With value: ' + item[itemKey]);
            }

            traverse(item[itemKey], key);
        }
    } else if (Array.isArray(item)) {
        // Array
        for (let i = 0; i < item.length; ++i) {
            traverse(item[i], key);
        }
    }
}

Any help would be greatly appreciated. Thank you for your time!

Sure you just need to return a flag of some kind to trigger the loops to stop

 /* * I am trying to search the following json array for any occurance of the key "statePath". * In a perfect world I would be able to find the first occurance, and return true from the * function. * * The following data is not real, I was just trying to write as much nested stuff as possible * to test that it traverses as far as needed. */ const data = [ { id: '2144d998-4c33-4b03-93d2-f6c675b24508', element: 'div', props: { className: 'testing', name: [ { first: 'John', last: { statePath: 'lastName', anArray: [ { anObject: { anotherArray: [ { doesItWork: { statePath: 'hello', }, }, ], }, }, ], }, }, { first: 'Jane', last: { statePath: 'lastName', }, }, ], }, children: 'hi', }, ]; function traverse(item, key) { if (typeof item === 'object' && !Array.isArray(item) && item !== null) { // Object for (let itemKey in item) { if (itemKey === key) { console.log('found the key: ' + itemKey + ' With value: ' + item[itemKey]); // not sure what you want the end "return" of the func to be, I'm returning the value. You could return true here instead, you could return a reference to the parent object, lots of possibilities return item[itemKey]; } var found = traverse(item[itemKey], key); if (found !== undefined) return found; // otherwise keep looking } } else if (Array.isArray(item)) { // Array for (let i = 0; i < item.length; ++i) { var found = traverse(item[i], key); if (found !== undefined) return found; } } } var value = traverse(data, 'statePath'); console.log("value is " + value); 

You could use for...in and store result in one var and then check that var before you call function again and break loop if value is found.

 const data = [{"id":"2144d998-4c33-4b03-93d2-f6c675b24508","statePath":"div","props":{"className":"testing","name":[{"first":"John","last":{"statePath":"lastName","anArray":[{"anObject":{"anotherArray":[{"doesItWork":{"statePath":"hello"}}]}}]}},{"first":"Jane","last":{"statePath":"lastName"}}]},"children":"hi"}] function traverse(item, key) { let result = false; for (var i in item) { if (i == key) { result = true; break; } if (typeof item[i] == 'object' && !result) { result = traverse(item[i], key) } } return result } console.log(traverse(data, 'statePath')) 

My variant:

 const data = [{id: '2144d998-4c33-4b03-93d2-f6c675b24508', element: 'div', props: {className: 'testing', name: [{first: 'John', last: {statePath3: 'lastName', anArray: [{anObject: {anotherArray: [{doesItWork: {statePath1: 'hello',},},],},},],},}, {first: 'Jane', last: {statePath: 'lastName',},},],}, children: 'hi',},]; function traverse(data, find) { for (let k in data) { let deepHaveKey = typeof data[k] === 'object' && traverse(data[k], find) if (find === k || deepHaveKey) return true } return false } console.log(traverse(data, 'statePath')); // true console.log(traverse(data, 'state')); // false 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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