从父子JSON数据中获取所有子项

时间:2021-07-02 20:20:10

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

我有父子JSON数据,我希望从所选父项中获取所有子项(嵌套子项)。

For example, I have JSON data :

例如,我有JSON数据:

[{
  "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 :

我有函数findAllChildren(1),其中“1”是“父”,然后函数的结果应该是:

[{
  "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 :

而在其他情况下,如果我调用findAllChildren(2),该函数的结果应如下所示:

[{
  "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.

创建函数来解决这种情况的正确方法是什么?谢谢。

3 个解决方案

#1


4  

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.

您可以迭代原始数据并查找具有指定标识为parent_id的项目。如果找到,则使用元素的id递归执行相同的操作。

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

在这里查看: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

#2


2  

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

我建议迭代所有数据并使用属性构建一个类似于对象的树,以使用所有给定的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; }

#3


1  

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

您可以使用Array.prototype.filter从数组中删除与谓词条件不匹配的项。

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.

filter将循环遍历数组并为每次迭代运行一个函数。返回值为true,该项将在返回的数组中。

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.

传递给过滤器的parentId函数是curry。它将锁定您在作用域中搜索的父ID,并返回过滤器将运行的函数。

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))
)

#1


4  

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.

您可以迭代原始数据并查找具有指定标识为parent_id的项目。如果找到,则使用元素的id递归执行相同的操作。

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

在这里查看: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

#2


2  

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

我建议迭代所有数据并使用属性构建一个类似于对象的树,以使用所有给定的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; }

#3


1  

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

您可以使用Array.prototype.filter从数组中删除与谓词条件不匹配的项。

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.

filter将循环遍历数组并为每次迭代运行一个函数。返回值为true,该项将在返回的数组中。

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.

传递给过滤器的parentId函数是curry。它将锁定您在作用域中搜索的父ID,并返回过滤器将运行的函数。

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))
)