Hidayat
Hidayat

Reputation: 83

Get all children from parent child JSON data

I have parent-child JSON data and I want get all children (nested children) from selected parent.

For example, I have JSON data :

[{
  "id": 1,
  "parent": 0,
  "name": "Parent"
}, {
  "id": 2,
  "parent": 1,
  "name": "Child 1"
}, {
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}, {
  "id": 5,
  "parent": 1,
  "name": "Child 2"
}]

And I have function findAllChildren(1), where "1" is "parent" and then result of function should be :

[{
  "id": 2,
  "parent": 1,
  "name": "Child 1"
}, {
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}, {
  "id": 5,
  "parent": 1,
  "name": "Child 2"
}]

And in other case, if i call findAllChildren(2), result of the function should like below :

[{
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}]

What is the proper way to create function to solve that case? Thank you.

Upvotes: 8

Views: 28241

Answers (3)

Nina Scholz
Nina Scholz

Reputation: 386620

I suggest to iterate all data and build a tree like object with properties to start the search with all given id.

Then the object is walked and the children iterated for the result.

function getDescendant(id) {
    var result = [];
    Array.isArray(object[id].children) && object[id].children.forEach(function iter(a) {
        result.push({ id: a.id, parent: a.parent, name: a.name });
        Array.isArray(a.children) && a.children.forEach(iter);
    });
    return result;
}

var data = [{ id: 1, parent: 0, name: "Parent" }, { id: 2, parent: 1, name: "Child 1" }, { id: 3, parent: 2, name: "Grand Child 1" }, { id: 4, parent: 2, name: "Grand Child 2" }, { id: 5, parent: 1, name: "Child 2" }],
    object = function (data, root) {
        var o = {};
        data.forEach(function (a) {
            a.children = o[a.id] && o[a.id].children;
            o[a.id] = a;
            o[a.parent] = o[a.parent] || {};
            o[a.parent].children = o[a.parent].children || [];
            o[a.parent].children.push(a);
        });
        return o;
    }(data, 0);

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

Upvotes: 2

Martin Gottweis
Martin Gottweis

Reputation: 2739

You can just iterate over the original data and look for items that has the specified id as parent_id. If found, do the same recursively with the element's id.

Check it out here: https://jsfiddle.net/6ydog1tj/2/

function findAllChildren (id, results, depth) {
    for (d in data) {
        if (data[d].parent == id) {
            data[d].depth = depth
            results.push(data[d])
            findAllChildren(data[d].id, results, depth + 1)
        }
    }
}

var results = []
findAllChildren(1, results, 0)

$('body').append(results.map(function (element) { return Array(element.depth + 1).join(' -> ') + element.name + '<br>' }))

console.log(results)

prints out

Child 1
-> Grand Child 1
-> Grand Child 2
Child 2

Upvotes: 8

synthet1c
synthet1c

Reputation: 6282

You can use Array.prototype.filter to remove items from an array that do not match a predicate condition.

filter will loop over an array and run a function for each iteration. it the return value is true the item will be in the returned array.

The parentId function passed into filter is curried. it will lock in the parent id you are searching for in the scope and return the function that filter will run.

const data = [{
  "id": 1,
  "parent": 0,
  "name": "Parent"
}, {
  "id": 2,
  "parent": 1,
  "name": "Child 1"
}, {
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}, {
  "id": 5,
  "parent": 1,
  "name": "Child 2"
}]

function parentId(id) {
  return function(item) {
    return item.parent === id
  }
}

console.log(
  data.filter(parentId(2))
)

Upvotes: 1

Related Questions