简体   繁体   中英

Parent and child relation setup from JSON

I have following JSON data:

[
 {id: 1, indent: '1'},
 {id: 2, indent: '1.1'},
 {id: 3, indent: '1.2'},
 {id: 4, indent: '2'},
 {id: 5, indent: '2.1'},
 {id: 6, indent: '2.2'},
 {id: 7, indent: '2.2.1'},
 {id: 8, indent: '1.2.1'},
 {id: 9, indent: '3'},
]

I want to convert it into like below:

[
 {id: 1, indent: '1', parent: null},
 {id: 2, indent: '1.1', parent: 1},
 {id: 3, indent: '1.2', parent: 1},
 {id: 4, indent: '2', parent: null},
 {id: 5, indent: '2.1', parent: 4},
 {id: 6, indent: '2.2', parent: 4},
 {id: 7, indent: '2.2.1', parent: 6},
 {id: 8, indent: '1.2.1', parent: 3},
 {id: 9, indent: '3', parent: null},
]

I can achieve this with 2 for loops, outer and inner but I'm looking for some efficient way to do it.

ex: 
forloop each node
   get indent and check if dots ('.') are more than one
     if true
     for-loop the array and check for indent that start with the indent and ends with dot + 1

Unless you are going to have more than 100000 of these items in your json (which seems unlikely as that would take a long time to download / send ) then your approach will work just fine.

The best optimization you could do would be to take advantage of the fact that the ids are in order. As the references are not, that is going to require you to keep track of the ids to indent references in an object as you move forward.

That would look like this

 var jsonObj = [ {id: 1, indent: '1'}, {id: 2, indent: '1.1'}, {id: 3, indent: '1.2'}, {id: 4, indent: '2'}, {id: 5, indent: '2.1'}, {id: 6, indent: '2.2'}, {id: 7, indent: '2.2.1'}, {id: 8, indent: '1.2.1'}, {id: 9, indent: '3'}, ]; var parentIds = {}; for(var i = 0; i < jsonObj.length; i++){ var obj = jsonObj[i]; var dot = obj.indent.lastIndexOf('.'); if(dot > -1){ obj.parent = parentIds[obj.indent.substr(0,dot)]; }else{ obj.parent = null; } parentIds[obj.indent] = obj.id; } console.log(jsonObj); document.querySelector("#d").innerHTML = JSON.stringify(jsonObj); 
 <div id="d"></div> 

You can create a map from indent to ID.

 var data = [{id: 1, indent: '1'}, {id: 2, indent: '1.1'}, {id: 3, indent: '1.2'}, {id: 4, indent: '2'},{id: 5,indent: '2.1'},{id: 6, indent: '2.2'}, {id: 7,indent: '2.2.1'},{id: 8, indent: '1.2.1'}, {id: 9, indent: '3'}]; var indentToId = {}; for (var i=0, item; item = data[i]; i++) { indentToId[item.indent] = item.id; } for (var i=0, item; item = data[i]; i++) { var lastPeriodIndex = item.indent.lastIndexOf('.'); // Added this as a performance tweak so it would compare to Travis's version :) if (lastPeriodIndex == -1) { item.parent = null; } else { // Again, stealing form Travis, subst is faster than slice item.parent = indentToId[item.indent.substr(0, lastPeriodIndex)]; } } console.log(JSON.stringify(data)); // [{"id":1,"indent":"1","parent":null},{"id":2,"indent":"1.1","parent":1}, // {"id":3,"indent":"1.2","parent":1},{"id":4,"indent":"2","parent":null}, // {"id":5,"indent":"2.1","parent":4},{"id":6,"indent":"2.2","parent":4}, // {"id":7,"indent":"2.2.1","parent":6},{"id":8,"indent":"1.2.1","parent":3}, // {"id":9,"indent":"3","parent":null}] 

You were concerned about there being two loops. However, the real problem is when you have nested loops. Two loops, one after the other, is still linear time. See this performance comparison .

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