2

I currently have an array of objects which I'm trying to reshape into a nested object with the ID as an object key, and target that ID with the parent id if it's not "0". I've tried several approaches but I'm struggling big time! The main stumbling block for me is anything beyond one or two layers deep. Ideally I need this to be dynamic so it can handle potentially any depth although in the wild I doubt it will go beyond 3 layers.

Here is the incoming array of objects:

[
 {
 ID: "1671",
 parent: "0",
 },
 {
 ID: "1223",
 parent: "0",
 },
 {
 ID: "1668",
 parent: "0",
 },
 {
 ID: "1688",
 parent: "0",
 },
 {
 ID: "1669",
 parent: "0",
 },
 {
 ID: "1681",
 parent: "1669",
 },
 {
 ID: "1680",
 parent: "1669",
 },
 {
 ID: "1670",
 parent: "1669",
 },
 {
 ID: "1682",
 parent: "1669",
 },
 {
 ID: "1433",
 parent: "1682",
 },
 {
 ID: "1684",
 parent: "1682",
 },
 {
 ID: "1672",
 parent: "1684",
 },
 {
 ID: "1685",
 parent: "1672",
 },
 {
 ID: "1686",
 parent: "1672",
 },
 {
 ID: "1683",
 parent: "0",
 },
 {
 ID: "1230",
 parent: "0",
 },
 {
 ID: "1667",
 parent: "0",
 },
 {
 ID: "1687",
 parent: "0",
 }
];

And here is the desired transformation:

1671: {
 ID: "1671",
 parent: "0",
 },
 1223: {
 ID: "1223",
 parent: "0",
 },
 1668: {
 ID: "1668",
 parent: "0",
 },
 1688: {
 ID: "1688",
 parent: "0",
 },
 1669: {
 ID: "1669",
 parent: "0",
 children: {
 1681: {
 ID: "1681",
 parent: "1669",
 },
 1680: {
 ID: "1680",
 parent: "1669",
 },
 1670: {
 ID: "1670",
 parent: "1669",
 },
 1682: {
 ID: "1682",
 parent: "1669",
 children: {
 1433: {
 ID: "1433",
 parent: "1682",
 },
 1684: {
 ID: "1684",
 parent: "1682",
 children: {
 1672: {
 ID: "1672",
 parent: "1684",
 children: {
 1685: {
 ID: "1685",
 parent: "1672",
 },
 1686: {
 ID: "1686",
 parent: "1672",
 }
 }
 }
 }
 }
 }
 }
 }
 },
 1683: {
 ID: "1683",
 parent: "0",
 },
 1230: {
 ID: "1230",
 parent: "0",
 },
 1667: {
 ID: "1667",
 parent: "0",
 },
 1687: {
 ID: "1687",
 parent: "0",
 }

Most of my failed approaches have been using Array.reduce() and other types of recursion but to no avail, so I'm interested to see if there is a solution for this.

Thanks

asked Apr 23, 2018 at 6:52
1
  • please add your try/tries. Commented Apr 23, 2018 at 6:52

2 Answers 2

5

You can use recursive function like this:

function findFor(parentId) {
 // create a new object to store the result
 var z = {};
 // for each item in a
 for (var i = 0; i<a.length; i++){
 // find all children of parentId
 if (a[i].parent === parentId) {
 // recursively find children for each children of parentId
 var ch = findFor(a[i].ID);
 // if it has no children, skip adding the children prop
 var o = Object.keys(ch).length === 0 ? {} : { children: ch };
 z[a[i].ID] = Object.assign(o, a[i]);
 }
 }
 return z;
}
// find all item whose parent is "0"
console.log(findFor("0"));

var a = [
 { ID: "1671", parent: "0", },
 { ID: "1223", parent: "0", },
 { ID: "1668", parent: "0", },
 { ID: "1688", parent: "0", },
 { ID: "1669", parent: "0", },
 { ID: "1681", parent: "1669", },
 { ID: "1680", parent: "1669", },
 { ID: "1670", parent: "1669", },
 { ID: "1682", parent: "1669", },
 { ID: "1433", parent: "1682", },
 { ID: "1684", parent: "1682", },
 { ID: "1672", parent: "1684", },
 { ID: "1685", parent: "1672", },
 { ID: "1686", parent: "1672", },
 { ID: "1683", parent: "0", },
 { ID: "1230", parent: "0", },
 { ID: "1667", parent: "0", },
 { ID: "1687", parent: "0", }
];
function findFor(parentId) {
 var z = {};
 for (var i = 0; i<a.length; i++){
 if (a[i].parent === parentId) {
 var ch = findFor(a[i].ID);
 var o = Object.keys(ch).length === 0 ? {} : { children: ch };
 z[a[i].ID] = Object.assign(o, a[i]);
 }
 }
 
 return z;
}
console.log(findFor("0"));

answered Apr 23, 2018 at 7:02
Sign up to request clarification or add additional context in comments.

Comments

1

A single loop non recursive approach by respecting the parents.

var flat = [{ ID: "1671", parent: "0" }, { ID: "1223", parent: "0" }, { ID: "1668", parent: "0" }, { ID: "1688", parent: "0" }, { ID: "1669", parent: "0" }, { ID: "1681", parent: "1669" }, { ID: "1680", parent: "1669" }, { ID: "1670", parent: "1669" }, { ID: "1682", parent: "1669" }, { ID: "1433", parent: "1682" }, { ID: "1684", parent: "1682" }, { ID: "1672", parent: "1684" }, { ID: "1685", parent: "1672" }, { ID: "1686", parent: "1672" }, { ID: "1683", parent: "0" }, { ID: "1230", parent: "0" }, { ID: "1667", parent: "0" }, { ID: "1687", parent: "0" }],
 tree = function (data, root) {
 var o = {};
 data.forEach(function(a) {
 a = Object.assign({}, a);
 if (o[a.ID] && o[a.ID].children) {
 a.children = o[a.ID].children;
 }
 o[a.ID] = { [a.ID]: a };
 o[a.parent] = o[a.parent] || {};
 o[a.parent][a.parent] = o[a.parent][a.parent] || {};
 o[a.parent][a.parent].children = o[a.parent][a.parent].children || {};
 o[a.parent][a.parent].children[a.ID] = a;
 });
 return o[root][root].children;
 }(flat, '0');
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

answered Apr 23, 2018 at 7:14

1 Comment

the levels are not restricted.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.