0

I am looking to turn this flat array into an nested array but it keeps returning as empty. Not sure how to solve this one or what I am missing but this is driving me crazy.

Flat array:

var names =[
{ name: 'b', parent: 'Brown' },
{ name: 'a', parent: 'Brown' },
{ name: 'h', parent: 'Green' },
{ name: 'c', parent: 'Green' },
];

Desired output of array:

[{
    name: 'Brown',
    children: [{
            name: 'a',
            children: []
        },
        {
            name: 'b',
            children: []
        }
    ]
}, {
    name: 'Green',
        children: [{
                name: 'h',
                children: []
            },
            {
                name: 'c',
                children: []
            }
        ]
    }
}]

Js:

function getNestedChildren(arr, parent) {
    var children = [];
    for(var i =0; i < arr.length; ++i) {
        if(arr[i].parent == parent) {
            var grandChildren = getNestedChildren(arr, arr[i].name)

            if(grandChildren.length) {
                arr[i].children = grandChildren;
            }
            children.push( arr[i]);
        }
    }
    return children;
}
var nest = getNestedChildren(names, names.parent);
console.log( nest);
user992731
  • 3,400
  • 9
  • 53
  • 83
  • `var nest = getNestedChildren(names, names.parent);` what is `names.parent`? `undefined`? – ASDFGerte May 02 '18 at 15:38
  • you have to loop through the names and call parent for each one names[0].parent (otherwise its undefined) – Luke Gaskell May 02 '18 at 15:40
  • I am trying to get to the root level of the array. Any thoughts? – user992731 May 02 '18 at 15:40
  • @user992731 use 0 to get the root level. See my answer below – dikuw May 02 '18 at 15:41
  • Also, this might be interesting for you: [how-to-group-an-array-of-objects-by-key](https://stackoverflow.com/questions/40774697/how-to-group-an-array-of-objects-by-key) (copied wrong link first, edited) – ASDFGerte May 02 '18 at 15:43
  • It seems to create an infinite recursion.... – Tiago Coelho May 02 '18 at 15:44
  • @TiagoCoelho it doesn't create anything, `names.parent` should be `undefined` and none of the elements have a `parent` that will be coerced to the same. Note aswell that usage of `==` instead of `===` is quite risky. – ASDFGerte May 02 '18 at 15:47

3 Answers3

1

You can create a new object, for each item assign an array to a key with the parent name, and concatenate the item to that array

var names =[
{ name: 'b', parent: 'Brown' },
{ name: 'a', parent: 'Brown' },
{ name: 'h', parent: 'Green' },
{ name: 'c', parent: 'Green' },
];

const getGroup=(groups, parent) => {
  let group = groups.find(g=>g.parent===parent);
  if(!group){
    group=({parent,children:[]});
    groups.push(group);
  }
  return group;
}

let  grouped = []
 names.forEach(item=> getGroup(grouped,item.parent).children.push(item))
 
                             
console.log(grouped)
Tiago Coelho
  • 5,023
  • 10
  • 17
1

var names =[
{ name: 'b', parent: 'Brown' },
{ name: 'a', parent: 'Brown' },
{ name: 'h', parent: 'Green' },
{ name: 'c', parent: 'Green' },
{ name: 'j', parent: 'Brown' }
];

function groupBy(arr, f) {
  return arr.reduce((r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r), {});
}

function nestArray(array){
  var newArray=[],
      resultGrouped = groupBy(names, function(c) {
    return c.parent
  });
  
  for (var key in resultGrouped){
    var item=resultGrouped[key];
    
    newArray.push({
      name:key,
      children:item.map(function(map){
        delete map.parent;
        map.children=[];
        return map;
      })
    });
  }
  
  return newArray;
}
console.log(nestArray(names));
LellisMoon
  • 4,810
  • 2
  • 12
  • 24
0

So for starters, you need to loop through the names and send each parent to your getNestedChildren() function.

var names =[
    { name: 'b', parent: 'Brown' },
    { name: 'a', parent: 'Brown' },
    { name: 'h', parent: 'Green' },
    { name: 'c', parent: 'Green' },
];

var nest = [];

for (var i = 0; i < names.length; i++) {
    nest.push(getNestedChildren(names, names[i].parent));
} 

Also your getNestedChildren() is currently trying to modify and send back the old names array. I'd suggest creating a new object instead and send back the object with the children on it.

function getNestedChildren(arr, parent) {
    var children = [];
    var parentObj = {};
    parentObj.name = parent;
    for(var i =0; i < arr.length; ++i) {
        if(arr[i].parent == parent) {
            children.push(getNestedChildren(arr, arr[i].name));
        }
    }
    parentObj.children = children;
    return parentObj;
}
Luke Gaskell
  • 175
  • 4
  • 15