Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Create recursive tree from json using lodash transform without recursion. Can have unlimited nesting.
var _ = require('lodash');
var arr = [
{"name":"my2child1","title":"My 2 Child 1","parent":"my2"},
{"name":"my2child2","title":"My 2 Child 2","parent":"my2"},
{"name":"parent","title":"A single parent"},
{"name":"child-parent","title":"A child parent","parent":"child1"},
{"name":"my","title":"My"},
{"name":"my2","title":"My2"},
{"name":"child1","title":"Child 1","parent":"my"},
{"name":"child2","title":"Child 2","parent":"my"}
];
var result = _.filter(arr, function(item){
var parentName = item.parent;
item.children = this(item.name);
return !(parentName && this(parentName).push(item));
}, _.memoize(function(){ return []; }));
console.log(JSON.stringify(result, null, 2));
// ==> output
//[
// {
// "name": "parent",
// "title": "A single parent",
// "children": []
// },
// {
// "name": "my",
// "title": "My",
// "children": [
// {
// "name": "child1",
// "title": "Child 1",
// "parent": "my",
// "children": [
// {
// "name": "child-parent",
// "title": "A child parent",
// "parent": "child1",
// "children": []
// }
// ]
// },
// {
// "name": "child2",
// "title": "Child 2",
// "parent": "my",
// "children": []
// }
// ]
// },
// {
// "name": "my2",
// "title": "My2",
// "children": [
// {
// "name": "my2child1",
// "title": "My 2 Child 1",
// "parent": "my2",
// "children": []
// },
// {
// "name": "my2child2",
// "title": "My 2 Child 2",
// "parent": "my2",
// "children": []
// }
// ]
// }
//]
@alonronin
Copy link
Author

alonronin commented Jul 25, 2015

@tweinfeld solution:

function transformToTree(arr){
    var nodes = {};    
    return arr.filter(function(obj){
        var id = obj["name"],
            parentId = obj["parent"];

        nodes[id] = _.defaults(obj, nodes[id], { children: [] });
        parentId && (nodes[parentId] = (nodes[parentId] || { children: [] }))["children"].push(obj);

        return !parentId;
    });    
}

var arr = [
    {"name":"my2child1","title":"My 2 Child 1","parent":"my2"},
    {"name":"my2child2","title":"My 2 Child 2","parent":"my2"},
    {"name":"parent","title":"A single parent"},
    {"name":"child-parent","title":"A child parent", "parent": "child1"},
    {"name":"my","title":"My"},
    {"name":"my2","title":"My2"},
    {"name":"child1","title":"Child 1","parent":"my"},
    {"name":"child2","title":"Child 2","parent":"my"}
];

var result = transformToTree(arr);

console.log(JSON.stringify(result, null, 2));

@alonronin
Copy link
Author

alonronin commented Jul 25, 2015

update it to be more functional using one iteration inspired by Tal Weinfeld.

@alonronin
Copy link
Author

alonronin commented Jul 25, 2015

update to be even more functional, thanx Tal 😄

@yogendra9891
Copy link

yogendra9891 commented Dec 15, 2016

[
{
"name": "parent",
"title": "A single parent",
"children": []
},
{
"name": "my",
"title": "My",
"children": [
{
"name": "child1",
"title": "Child 1",
"parent": "my",
"children": [
{
"name": "child-parent",
"title": "A child parent",
"parent": "child1",
"children": []
}
]
},
{
"name": "child2",
"title": "Child 2",
"parent": "my",
"children": []
}
]
},
{
"name": "my2",
"title": "My2",
"children": [
{
"name": "my2child1",
"title": "My 2 Child 1",
"parent": "my2",
"children": []
},
{
"name": "my2child2",
"title": "My 2 Child 2",
"parent": "my2",
"children": []
}
]
}
]

this is my json

I need all parents name of a each node.

@MrEldin
Copy link

MrEldin commented Jul 4, 2018

Hi @alonronin, i tried this one, and I got error:

"this is not a function"

What I'm doing wrong?

@alonronin
Copy link
Author

alonronin commented Dec 24, 2018

@MrEldin it was with lodash 3, need to refactor to 4 remove the this or use bind.

@samvirkar144
Copy link

samvirkar144 commented Dec 26, 2018

Hi @alonronin, @MrEldin ,Is there any external library or npm package that can handle very large files (Millions json object in array) by passing specific column. Thank you...

@tanveerbyn
Copy link

tanveerbyn commented Apr 12, 2019

@LFTroya
Copy link

LFTroya commented Jul 29, 2019

_.defaults

I think you could replace _.defaults with Object.assign() and remove lodash dependency

@stzach
Copy link

stzach commented Feb 19, 2021

Hello,

Looking to enhance your functionality with ordering and also create the opposite tree2recursive function.

var arr = [
{ id: "0", title: "ROOT", parentId: "", order: 1 },
{ id: "30", title: "My 2 Child 1", parentId: "3", order: 2 },
{ id: "31", title: "My 2 Child 2", parentId: "3", order: 1 },
{ id: "1", title: "A single parent", parentId: "0", order: 3 },
{ id: "200", title: "A child parent", parentId: "20", order: 1 },
{ id: "2", title: "My", parentId: "0", order: 1 },
{ id: "3", title: "My2", parentId: "0", order: 2 },
{ id: "20", title: "Child 1", parentId: "2", order: 2 },
{ id: "21", title: "Child 2", parentId: "2", order: 1 }
];

So the arr item is having order so all items are order in the tree children property. Also maybe there is a ROOT element, but this is not important as you can easily add it later on. Any thoughts on that?

@amirshnll
Copy link

amirshnll commented Jun 23, 2022

First, you need install loash with below command with npm:

npm i lodash

Second, you must import _ from loash

import _ from "lodash";

Finally, run this function:

export const recursive_lists = (data) => {
  const grouped = _.groupBy(data, (item) => item. parent_id);

  function childrenOf(parent_id) {
    return (grouped[parent_id] || []).map((item) => ({
      id: item.id,
      title: item.title,
      child: childrenOf(item.id),
    }));
  }

  return childrenOf(null);
};

or

First:

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>

Second:

function recursive_lists(data) {
  const grouped = _.groupBy(data, (item) => item.parent_id);

  function childrenOf(parent_id) {
    return (grouped[parent_id] || []).map((item) => ({
      id: item.id,
      title: item.title,
      child: childrenOf(item.id),
    }));
  }

  return childrenOf(null);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment