2

My code:

function convert(arr, parent) {
    var out = [];
    for(var i in arr) {
        if(arr[i].parent == parent) {
            var children = convert(arr, arr[i].id)

            if(children.length) {
                arr[i].children = children
            }
            out.push(arr[i])
        } 
    }
    return out; //return Object.assign({}, out);tried this, but i lose parents childrens arrays
};
arras = [
    {id: 1, name: "parent1", parent: null},
    {id: 2, name: "children1", parent: 1},
    {id: 3, name: "children2", parent: 1},
    {id: 4, name: "parent2", parent: null},
    {id: 5, name: "children3", parent: 4},
    {id: 6, name: "children4", parent: 4}
]
console.log(convert(arras, null));

How final result should look

{
    parent1: [
        {name: "children1"},
        {name: "children2"}
    ],
    parent2: [
        {name: "children3},
        {name: "children4"}
    ]
}

What my output looks so far:

[
  {id: 1, name: "parent1", parent: null}: [
        {id: 2, name: "children1", parent: 1},
        {id: 3, name: "children2", parent: 1},
    ],
  {id: 4, name: "parent2", parent: null}: [
        {id: 5, name: "children3", parent: 4},
        {id: 6, name: "children4", parent: 4}
    ]
]

So firstly, what I have to do is convert main array to object, when I tend to do that, I lose both parent object arrays...Also need to change the way console displays objects, any help is appreciated.

5 Answers 5

2

You could build a tree with check if parent is a root node or not.

var data = [{ id: 1, name: "parent1", parent: null }, { id: 2, name: "children1", parent: 1 }, { id: 3, name: "children2", parent: 1 }, { id: 4, name: "parent2", parent: null }, { id: 5, name: "children3", parent: 4 }, { id: 6, name: "children4", parent: 4 }],
    tree = function (data, root) {
        var r = {},
            o = {};

        data.forEach(function (a) {
            if (a.parent === root) {
                r[a.name] = [];
                o[a.id] = r[a.name];
            } else {
                o[a.parent] = o[a.parent] || [];
                o[a.parent].push({ name: a.name });
            }
        });
        return r;
    }(data, null);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

2

Try this.

function convert(arr) {
  var parents = {};
  for (var i in arr) {
    if (arr[i].parent === null) {
      parents[arr[i].id] = arr[i].name
    }
  }

  var out = {}
  for (i in arr) {
    if (arr[i].parent !== null) {
      var parentName = parents[arr[i].parent];
      if (out.hasOwnProperty(parentName)) {
        out[parentName].push(arr[i].name)
      } else {
        out[parentName] = [arr[i].name]
      }
    }
  }
  return out;
};
arras = [{
    id: 1,
    name: "parent1",
    parent: null
  },
  {
    id: 2,
    name: "children1",
    parent: 1
  },
  {
    id: 3,
    name: "children2",
    parent: 1
  },
  {
    id: 4,
    name: "parent2",
    parent: null
  },
  {
    id: 5,
    name: "children3",
    parent: 4
  },
  {
    id: 6,
    name: "children4",
    parent: 4
  }
]
//console.log(convert(arras, null));
alert(JSON.stringify(convert(arras)));

But notice for multilevel it doesn't work correctly. If your need it, your must save map for all possible parent list

2 Comments

The function kind of fails to deal with child ids that dont have a parent id, assigning all unmatched child names to an array arras.undefined which is not a good name for a property. Also those child's parent id is lost in the process which would be a major fail.
@Blindman67 You notice is correct if input data will contain records without doesn't hape property parent. But as for me it just wrong input data
2
arras.forEach(function(el){
    if(el.parent){
      el.parent=arras.find(e=>e.id==el.parent)||(console.error("no parent:"+el.parent),undefined);
    }
 });
 //resolved parent/childs....
 var newmodel = arras.reduce(function(obj,el){
   if(el.parent){
    //child
    obj[el.parent.name]=obj[el.parent.name]||[];//create new parent if neccessary
    obj[el.parent.name].push({name:el.name});
   }else{
    //parent
    obj[el.name]=obj[el.name]||[];
  }
  return obj;
  },{});

http://jsbin.com/renicijufi/edit?console

2 Comments

You got typo aras.reduce
Your function fails if an id is zero
1

Another way:

var arrays = [
    {id: 1, name: 'parent1', parent: null},
    {id: 2, name: 'children1', parent: 1},
    {id: 3, name: 'children2', parent: 1},
    {id: 4, name: 'parent2', parent: null},
    {id: 5, name: 'children3', parent: 4},
    {id: 6, name: 'children4', parent: 4}
];

// First, reduce the input arrays to id based map
// This step help easy to select any element by id.
arrays = arrays.reduce(function (map, el) {
    map[el.id] = el;

    return map;
}, {});

var result = Object.values(arrays).reduce(function (result, el) {
    if (!el.parent) {
        result[el.name] = [];
    } else {
        result[arrays[el.parent].name].push(el.name);
    }

    return result;
}, {});

console.log(result);

1 Comment

Your function fails if a child has an id of zero. Messing up the whole result
1

I think this meets your requirement

Obj = new Object();

for( i in arras){

    person = arras[i];

    if(person.parent != null){
        if(!Obj.hasOwnProperty(person.parent)){
            // here instead of the index you can use Obj["parent"+person.parent] get the exact thing. If you are using that use tha in rest of the code 
            Obj[person.parent] = new Array();
        }

        Obj[person.parent].push(person);    
    }
    else{
        if(!Obj.hasOwnProperty(person.id)){
            // Some parents might have kids not in the list. If you want to ignore, just remove from the else. 
            Obj[person.id] = new Array()
        }
    }
}

Edit :

Obj = new Object();

for( i in arras){

    person = arras[i];

    if(person.parent != null){
        if(!Obj.hasOwnProperty(person.parent)){
            // here instead of the index you can use Obj["parent"+person.parent] get the exact thing. If you are using that use tha in rest of the code 
            Obj[person.parent] = new Array();
        }

        Obj[person.parent].push({name : person.name});  
    }
    else{
        if(!Obj.hasOwnProperty(person.id)){
            // Some parents might have kids not in the list. If you want to ignore, just remove from the else. 
            Obj[person.id] = new Array()
        }
    }
}

Hope this helps. :)

2 Comments

Yours is the only one to correctly handled all test use cases I threw at it, not losing data, not incorrectly grouping children (maybe throw if no matching parent), apart from one minor point. The result is not matching required structure. data.parentName : [{name : childName},...
Check the edit. Thank you for the compliment. Pleasure helping ya. :)

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.