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

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"));

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; }

1 Comment

the levels are not restricted.

Your Answer

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.