coder fire
coder fire

Reputation: 1063

Transform array of objects to nested array

I have the array of objects

[  
 { id: 1, parent_id: null, title: 'Title 1' },
 { id: 2, parent_id: 1, title: 'Title2' },
 { id: 3, parent_id: 2, title: 'Title 3' },
 { id: 4, parent_id: null, title: 'Title 4' }  
]

I need to transform this array to this

[ 
  { 
    id: 1,
    parent_id: null,
    children: [  
        { 
          id: 2,
          parent_id: 1,
          title: 'Title2',
          children: [ 
            {  id: 3, parent_id: 2, title: "Title 3" } 
          ] 
        }
    ]
  },  
  {id: 4, parent_id: null, title: 'Title 4' } 
] 

I have no idea, how can do this

Upvotes: 0

Views: 53

Answers (3)

Reynier Rivero
Reynier Rivero

Reputation: 2392

Try with this recursion:

function update(item) {
    if (item.parent_id) {
        const parent = arr.findIndex(p => p.id === item.parent_id);
        if (!arr[parent].children)
            arr[parent].children = [];
        const index = arr[parent].children.findIndex(ch => ch.id === item.id);
        if (index >= 0)
            arr[parent].children.splice(index, 1);
        arr[parent].children.push(item);
        update(arr[parent]);
    }
}

arr.forEach(item => update(item));
arr = arr.filter(item => !item.parent_id);

console.log(arr);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386578

You could take a standard approach for generating a tree from data with id and parent id.

var data = [{ id: 1, parent_id: null, title: 'Title 1' }, { id: 2, parent_id: 1, title: 'Title2' }, { id: 3, parent_id: 2, title: 'Title 3' }, { id: 4, parent_id: null, title: 'Title 4' }],
    tree = function (data, root) {
        var t = {};
        data.forEach(o => {
            Object.assign(t[o.id] = t[o.id] || {}, o);
            t[o.parent_id] = t[o.parent_id] || {};
            t[o.parent_id].children = t[o.parent_id].children || [];
            t[o.parent_id].children.push(t[o.id]);
        });
        return t[root].children;
    }(data, null);

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

Upvotes: 0

twharmon
twharmon

Reputation: 4272

I think this will work:

const original = [  
 { id: 1, parent_id: null, title: 'Title 1' },
 { id: 2, parent_id: 1, title: 'Title2' },
 { id: 3, parent_id: 2, title: 'Title 3' },
 { id: 4, parent_id: null, title: 'Title 4' }  
]


const transform = arr => {
  for (let i = arr.length - 1; i >= 0; i--) {
    const post = arr[i]
    const parent = arr.find(p => p.id === post.parent_id)
    if (parent) {
      if (!parent.children) {
        parent.children = []
      }
      parent.children.push(post)
      post.duplicate = true
    }
  }
  for (let i = arr.length - 1; i >= 0; i--) {
    if (arr[i].duplicate) {
        arr.splice(i, 1)
    }
  }
  return arr
}

console.log(transform(original))

Here is the fiddle: https://jsfiddle.net/7h8mj63e/

Upvotes: 1

Related Questions