1

Given an array like this, where the maximum depth can be 3 levels and where we don't know at what level the researched item could be:

const data = {
         id: '1',
         children: [
             {
               id: '2',
               name: 'nameTest',
               children: [
                     {
                       id: '3'
                       name: 'deepLevel'
                      }
                ]
              }
          }

how can I add a property to the third level knowing only the value 'deepLevel' ? we are allowed to use lodash and strongly encouraged to use ES6.

the final dataStructure should be

Given an array like this, where the maximum depth can be of 3 levels:

const data = {
         id: '1',
         children: [
             {
               id: '2',
               name: 'nameTest',
               children: [
                     {
                       id: '3'
                       name: 'deepLevel'
                       addedProperty: true,
                      }
                ]
              }
        }
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
Legeo
  • 784
  • 4
  • 20
  • 44
  • 1
    Welcome to Stack Overflow! Visit the [help], take the [tour] to see what and [ask]. Please first ***>>>[Search for related topics on SO](https://www.google.com/search?q=javascript+add+deeply+nested+object+site%3Astackoverflow.com)<<<*** and if you get stuck, post a [mcve] of your attempt, noting input and expected output using the [`[<>]`](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do) snippet editor. – mplungjan Jan 05 '22 at 13:41

1 Answers1

2

An approach was to separate the tasks of finding a nested item by a custom(izable) entry (key-value pair) and assigning additional custom data to the found item.

Thus one e.g. could implement two methods recursivelyFindItemByEntry which is based on self recursion and a simple assignToObjectWithFirstMatchingNestedEntry which assigns provided data to the result of the former function invocation ...

function recursivelyFindItemByEntry(obj, [key, value]) {
  let item;

  if (!!obj && (typeof obj === 'object')) {
    if (
      obj.hasOwnProperty(key) &&
      (obj[key] === value)
    ) {
      item = obj;

    } else if (
      obj.hasOwnProperty('children') &&
      Array.isArray(obj.children)
    ) {
      obj.children.some(child => {

        item = recursivelyFindItemByEntry(child, [key, value]);
        return !!item;
      });
    }
  }
  return item;
}

function assignToObjectWithFirstMatchingNestedEntry(obj, [key, value], data) {
  Object.assign(
    recursivelyFindItemByEntry(obj, [key, value]) ?? {},
    data ?? {}
  );
  return obj;
}

const data = {
  id: '1',
  children: [{
    id: '2',
    name: 'nameTest',
    children: [{
      id: '3',
      name: 'deepLevel',
    }, {
      id: '4',
      name: 'deepLevel',
    }],
  }, {
    id: '5',
    name: 'nameTest',
    children: [{
      id: '6',
      name: 'deepLevel',
    }, {
      id: '7',
      name: 'deepLevelTarget',
      // addedProperty: true,
    }, {
      id: '8',
      name: 'deepLevel',
    }],
  }, {
    id: '9',
    name: 'nameTest'
  }, {
    id: '10',
    name: 'nameTestTarget'
  }, {
    id: '11',
    name: 'nameTest'
  }],
};

console.log(
  "recursivelyFindItemByEntry(data, ['name', 'deepLevelTarget']) ...",
  recursivelyFindItemByEntry(data, ['name', 'deepLevelTarget'])
);
console.log(
  "recursivelyFindItemByEntry(data, ['id', '10']) ...",
  recursivelyFindItemByEntry(data, ['id', '10'])
);
console.log('\n');

console.log(
  "recursivelyFindItemByEntry(data, ['id', 'foo']) ...",
  recursivelyFindItemByEntry(data, ['id', 'foo'])
);
console.log(
  "recursivelyFindItemByEntry(data, ['id', '1']) ...",
  recursivelyFindItemByEntry(data, ['id', '1'])
);
console.log('\n');

console.log(
  "assignToObjectWithFirstMatchingNestedEntry(data, ['name', 'deepLevelTarget']), { addedProperty: true } ...",
  assignToObjectWithFirstMatchingNestedEntry(data, ['name', 'deepLevelTarget'], { addedProperty: true })
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
  • 1
    what if i'm not able to know the depth of the researched item ? i give to your answer a thumb up :) ty for the answer. – Legeo Jan 05 '22 at 14:53
  • 1
    @Legeo ... the above `recursivelyFindItemByEntry ` is implemented agnostic to any nesting level. One does not need to know anything about the object except for being sure about it never violates the recursive data structure. In addition one needs to know that the query task stops with the first matching key-value pair. Thus, in case of deeper nested equal entries, any of them gets skipped. – Peter Seliger Jan 05 '22 at 15:34