0

I have original nested object which contains the huge tree kind of structure. This is is basically JSON string which is converted into JavaScript object.

Structure is like -

original = {
       type :  "table",
       children :[
           {
             type : "cell",
             children : [
                {
                   type : "label",
                   children : []
                }
             ]
           }
           {
             type : "cell",
             children : []
           }
       ]
    }

I have selected item as -

var select = original.children[1].children[0];

What I want is get the parent of selected item.

Here is sample demo - https://stackblitz.com/edit/angular-v5m9ua

Note : I need to trace over the original object to find the parent. I had looked at the other answers but they had mentioned how to design the object structure to get the parent but I don't want to change the original object.

Sunil Singh
  • 11,001
  • 2
  • 27
  • 48
  • @mirakurun and @Andy I have checked the answers which are mentioned as `duplicated of` but its a bit different since I don't have choice to modify the original object. – Sunil Singh Dec 08 '18 at 13:29
  • @Andy - its just an example, I could have any random selected child. – Sunil Singh Dec 08 '18 at 13:38
  • 1
    @SunilSingh — It isn't different. If you can't implement the solution, then you can't solve the problem. – Quentin Dec 08 '18 at 13:39
  • @Quentin - First of all it should be the solution as per problem. Second I know there is alternative solution. I am just looking for better way to implement it. – Sunil Singh Dec 08 '18 at 13:42
  • @SunilSingh — An answer which says "You can't" is still an answer. – Quentin Dec 08 '18 at 13:43
  • @quentin I disagree. This question is totally different, as the OP stated he does not want to change his datastructure, which the dupe requires. – Jonas Wilms Dec 08 '18 at 13:44
  • @JonasWilms — The duplicate *question* did not require that. That was just the recommendation of the accepted answer. – Quentin Dec 08 '18 at 13:46
  • 1
    Then there is no way then traversing a known ancestor object down to the one you are looking for [Find an object in an array of deeply nested objects recursively](https://stackoverflow.com/questions/46062970), [javascript find by value deep in a nested object/array](https://stackoverflow.com/questions/45336281) but based on your question you already know that, so what is the problem you have with that approach? – t.niese Dec 08 '18 at 13:47
  • 1
    @Quentin - this is really weird. You are forcing someone to implemented the solution just because it looks right to you and its top voted. You cannot, at least let someone help on this. I cannot create my problem state from solution. It must be vice versa. – Sunil Singh Dec 08 '18 at 13:51
  • 1
    [Javascript objects: get parent](https://stackoverflow.com/questions/2980763/javascript-objects-get-parent) – t.niese Dec 08 '18 at 13:56
  • `original` does not hold JSON but a JavaScript Object. JSON is a string based representation of data. – t.niese Dec 08 '18 at 14:22
  • @t.niese - thank you for pointing it out. I have updated the question. – Sunil Singh Dec 08 '18 at 14:25
  • @SunilSingh — There is nothing requiring that you implement the top voted or accepted answer of a duplicate question. There is nothing stopping you from using a different answer to the duplicate. There is nothing stopping people adding new answers to a duplicate question. – Quentin Dec 09 '18 at 01:09

2 Answers2

1

You could create recursive function with for...in loop and return last parent element that was of object type.

const data = {
  type: "table",
  children: [{
    type: "cell",
    children: [{
      type: "label",
      children: []
    }]
  }, {
    type: "cell",
    children: []
  }]
}
var select = data.children[0].children[0];

function getParent(data, obj, parent = null) {
  let result = null;

  (function loop(data, obj, parent) {
    if (typeof data == 'object' && !Array.isArray(data)) {
      parent = data
    }

    for (let i in data) {
      if (select == data[i]) {
        result = parent;
        break;
      }

      if (typeof data[i] == 'object') {
        loop(data[i], obj, parent)
      }
    }
  })(data, obj, parent)

  return result;
}

let parent = getParent(data, select)
console.log(parent)
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
  • Your implementation can handle the more complicated unknown tree structure including my case. However answer of @Jonas Wilms is pretty simple which meets my requirement. Thank you for your answer :) – Sunil Singh Dec 08 '18 at 14:32
0

You could search the tree:

 findParent(root, toFind) {
    for(const child of root.children || []) {
      if(child === toFind){
         return root;
      } 
      const result = this.findParent(child, toFind);
      if(result){
        return result;
      } 
    }
}

That can be used as:

  findParent(original, select)
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • You could have added a new answer to the duplicate instead of reopening this quesiton. – Quentin Dec 08 '18 at 13:44
  • @quentin again. the questions are different. Thats why I reopened. – Jonas Wilms Dec 08 '18 at 13:45
  • Its working with selected item `this.parent.children[0]` but not with ` this.parent.children[1];` - here is the demo - https://stackblitz.com/edit/angular-v5m9ua – Sunil Singh Dec 08 '18 at 14:01
  • @sunil cause the structure is different. All nodes have to have a `children` property, or you habe to handle the case that `root.children` is undefined. – Jonas Wilms Dec 08 '18 at 14:06
  • It tried with undefined check but did not work . Looks very close just small piece is missing here. – Sunil Singh Dec 08 '18 at 14:13
  • 1
    I edited the answer which is working for me. It require more testing but looks fine so far. Thank you for your help :) – Sunil Singh Dec 08 '18 at 14:18