Home > Net >  How recursively return array of object and nested object keys with full path?
How recursively return array of object and nested object keys with full path?

Time:01-14

I haven't been learning JS for a long time, so I don't really understand how the stack and recursion work yet. The task is to display an array of object keys, and if the object is nested, then display not only the name of the key, but also the name of the parent object.

For example, we have an object:

{
    a: {
        b: 2,
        q: [0, 3, 4],
    },
    x: true,
    d: { f: null,
         c: 'something' 
        }
}

So, goal is to return an array of keys:

[
  'a.b',   'a.q',
  'a.q.0', 'a.q.1',
  'a.q.2', 'x',
  'd.f',   'd.c'
]

As you can see, nested keys need to have a fully qualified name, including the parent name separated by a dot.

I solved this problem, but with a huge nesting of conditional statements and loops, and specifically for this object. That is, if you add one more nesting, the function will not work.

function getKeysArray(obj) {
    let array = [];
    for (const key of Object.keys(obj)) {
        if (typeof obj[key] !== 'object') {
            array.push(key);
        }
        let internObj = obj[key];
        
        if (typeof internObj === 'object') {
            for (const innerKey of Object.keys(internObj)) {
                array.push(`${key}.${innerKey}`);
                let mostInnerKey = internObj[innerKey];

                if (typeof mostInnerKey === 'object' && internObj[innerKey] !== null) {
                    for (const index of Object.keys(mostInnerKey)) {
                        array.push(`${key}.${innerKey}.${index}`)
                    }
                }
            }
        }
    }
    return array;
}

I believe that you can solve this problem using recursion, I solved a similar problem, but it was necessary to display the values, not the keys, and it was solved quite simply.

How to solve this with recursion - I do not know.

I also saw solutions to similar problems on StackOverflow, but it was not necessary to display the full name of the keys this way.

CodePudding user response:

You could take a recursive approach and have a look to objects.

const
    getPathes = o => Object
        .entries(o)
        .flatMap(([k, v]) => v && typeof v === 'object'
            ? getPathes(v).map(p => `${k}.${p}`)
            : k
        ),
    data = { a: { b: 2, q: [0, 3, 4] }, x: true, d: { f: null, c: 'something' } },
    pathes = getPathes(data);

console.log(pathes);

CodePudding user response:

const data = {"a":{"b":2,"q":[0,3,4]},"x":true,"d":{"f":null,"c":"something"}}

const f = (x, prefix='') =>
  Object.entries(x).flatMap(([k,v])=>[
    ...(Array.isArray(v) || !(v instanceof Object)) ? [`${prefix}${k}`]:[],
    ...v instanceof Object ? f(v, `${prefix}${k}.`):[]
  ])

console.log(f(data))

  • Related