【问题标题】:Get all children from parent child JSON data从父子 JSON 数据中获取所有子节点
【发布时间】:2016-10-11 11:19:39
【问题描述】:

我有父子 JSON 数据,我想从选定的父级获取所有子级(嵌套子级)。

例如,我有 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"
}]

我有函数 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"
}]

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

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

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

【问题讨论】:

  • 请添加想要的结果。数据是否有序?你有比上面更多的嵌套级别吗?如果您想获得id = 1,应该发生什么?
  • 已经改进

标签: javascript jquery json algorithm search


【解决方案1】:

您可以只遍历原始数据并查找具有指定 id 作为 parent_id 的项目。如果找到,则对元素的 id 递归执行相同操作。

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

打印出来

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

【讨论】:

  • 嗨,马丁,我也想获取包含孙子的数据。
  • 你能用给定输入的期望输出来改变你的问题吗?在问题 It fetches items with parent=2.
  • 我现在明白了。改了答案和jsfiddle,看看
  • 不客气。祝你的项目好运。嘿,也许您还可以以嵌套方式构造数据以使这更容易。在这里查看:jsfiddle.net/eokf884p/1
  • 感谢您的建议。也许是另一种情况,因为我从 RDBMS 中检索数据。
【解决方案2】:

我建议迭代所有数据并构建一个带有属性的树状对象,以使用所有给定的id 开始搜索。

然后该对象被遍历并且孩子们迭代结果。

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; }

【讨论】:

  • 嗨@nina-scholz,我想获取包括孙子在内的数据。例如:如果我通过 parent=1,我应该得到 id=2 的数据,包括节点的子节点。
  • 感谢@nina-scholz 的帮助,我从马丁那里得到了很好的解决方案。
【解决方案3】:

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

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

传递给过滤器的parentId 函数是curried。它将锁定您在范围内搜索的父 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))
)

【讨论】:

  • 嗨@synthet1c,我也想获取包括孙子的数据。
  • @Hidayat 你的意思是你想把它构造成一棵树吗?
  • 没有。我想从父节点搜索孩子和孙子(嵌套)。
猜你喜欢
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多