-1

I need a function that takes as its first parameter an object, and as its second parameter a string to pass through to get the value. If any of the properties is not found, the function returns undefined.

I can do it with reduce. but how can I do it with recursion? will it be faster with recursion?

const obj = {a: {b: {c: {d: 'Hello'}}}}

function optionalChaining (obj, path) {
  // recursion solution

}

expected result:

optionalChaining(obj, "a.b.c"); // { d: 'Hello' }
optionalChaining(obj, "a.b.c.d"); // Hello
optionalChaining(obj, "a.b.c.d.e"); // undefined
optionalChaining(obj, "b.d.a"); // undefined
Will Black
  • 350
  • 2
  • 17

3 Answers3

1

You can use recursion in each iteration, by splitting the path and trying to find if the key exists in the object.

  • The first iteration.

obj will be {a: {b: {c: {d: 'Hello'}}}} and index will be 0 so the key will be a

  • The second iteration.

obj will be {b: {c: {d: 'Hello'}}} and index will be 1 so the key will be b

And so on, until the obj undefined or the index be more than path length after splitting the dot . to stop the recursion.

const obj = {a: {b: {c: {d: 'Hello'}}}}

function optionalChaining (obj, path, index = 0) {

  if(obj === undefined) return
  if (path.split('.').length <= index) return obj

  return optionalChaining(obj[path.split('.')[index]], path, index + 1)
}

console.log(optionalChaining(obj, "a.b.c")); // { d: 'Hello' }
console.log(optionalChaining(obj, "a.b.c.d")); // Hello
console.log(optionalChaining(obj, "a.b.c.d.e")); // undefined
console.log(optionalChaining(obj, "b.d.a")); // undefined
Mina
  • 14,386
  • 3
  • 13
  • 26
1

With recursion you can do something like this.
Function has 4 lines of code and it doesn't need any kind of index tracing.

const obj = {a: {b: {c: {d: 'Hello'}}}}

function optionalChaining (obj, path) {
  const [key, nextPath] = path.split(/\.(.*)/s);
  if (!obj[key]) return undefined;
  if (!nextPath) return obj[key];
  return optionalChaining(obj[key], nextPath);
}

console.log(optionalChaining(obj, "a.b.c")); // { d: 'Hello' }
console.log(optionalChaining(obj, "a.b.c.d")); // Hello
console.log(optionalChaining(obj, "a.b.c.d.e")); // undefined
console.log(optionalChaining(obj, "b.d.a")); // undefined

Will it be faster with recursion?
We didn't see your solution with reduce but the difference will probably be unrecognizable (it still has to iterate over each part of path).

Jax-p
  • 7,225
  • 4
  • 28
  • 58
1

You could split the path and check if the path is empty.

const
    optionalChaining = (object, path) => {
        const
            [key, ...rest] = path.split('.');

        return path
            ? optionalChaining(object?.[key], rest.join('.'))
            : object;
    },
    obj = { a: { b: { c: { d: 'Hello' } } } };

console.log(optionalChaining(obj, "a.b.c")); // { d: 'Hello' }
console.log(optionalChaining(obj, "a.b.c.d")); // Hello
console.log(optionalChaining(obj, "a.b.c.d.e")); // undefined
console.log(optionalChaining(obj, "b.d.a")); // undefined
console.log(optionalChaining(obj, "")); // complete object
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392