根据父 ID JavaScript 将对象作为子对象

  • 本文关键字:对象 JavaScript ID javascript
  • 更新时间 :
  • 英文 :


>我有以下数据来自API

[
{
"Code": "01002",
"ParentAccountId": "01",
},
{
"Code": "01001001003",
"ParentAccountId": "01001001",
},
{
"Code": "01001004",
"ParentAccountId": "01001",
},
{
"Code": "02",
"ParentAccountId": null,
},
{
"Code": "01002001",
"ParentAccountId": "01002",
},
{
"Code": "02002",
"ParentAccountId": "02",
},
{
"Code": "02001",
"ParentAccountId": "02",
},
{
"Code": "01001001001",
"ParentAccountId": "01001001",
},
{
"Code": "03",
"ParentAccountId": null,
},
{
"Code": "01002002",
"ParentAccountId": "01002",
},
{
"Code": "03001",
"ParentAccountId": "03",
},
{
"Code": "01",
"ParentAccountId": null,
},
{
"Code": "01001001002",
"ParentAccountId": "01001001",
},
{
"Code": "01001002",
"ParentAccountId": "01001",
},
{
"Code": "01001001",
"ParentAccountId": "01001",
},
{
"Code": "01001003",
"ParentAccountId": "01001",
},
{
"Code": "01001005",
"ParentAccountId": "01001",
},
{
"Code": "01001",
"ParentAccountId": "01",
}
]

看看ParentAccountId.

由于我需要将其传递给treeview组件,因此我需要将其转换为如下所示的内容:

[
{
"Code": "01",
"ParentAccountId": null,
"children": [
{
"Code": "01001",
"ParentAccountId": "01",
"children": [
{
"Code": "01001001",
"ParentAccountId": "01001",
"children": [
{
"Code": "01001001001",
"ParentAccountId": "01001001",
"children": [],
},
{
"Code": "01001001002",
"ParentAccountId": "01001001",
"children": [],
},
{
"Code": "01001001003",
"ParentAccountId": "01001001",
"children": [],
},
],
},
{
"Code": "01001002",
"ParentAccountId": "01001",
"children": [],
},
{
"Code": "01001003",
"ParentAccountId": "01001",
"children": [],
},
{
"Code": "01001004",
"ParentAccountId": "01001",
"children": [],
},
{
"Code": "01001005",
"ParentAccountId": "01001",
"children": [],
}
],
},
{
"Code": "01002",
"ParentAccountId": "01",
"children": [
{
"Code": "01002001",
"ParentAccountId": "01002",
"children": [],
},
{
"Code": "01002002",
"ParentAccountId": "01002",
"children": [],
},
],
},
],
},
{
"Code": "02",
"ParentAccountId": null,
"children": [
{
"Code": "02001",
"ParentAccountId": "02",
"children": [],
},
{
"Code": "02002",
"ParentAccountId": "02",
"children": [],
},
],
},
{
"Code": "03",
"ParentAccountId": null,
"children": [
{
"Code": "03001",
"ParentAccountId": "03",
"children": [],
},
],
},
]

我想根据code使对象成为其父对象的子对象。该方案是,如果ParentAccountId为空,则它是顶级父级,如果ParentAccountId长度为 2,则它是第 1 级子级,如果ParentAccountId长度为 5,则它是第 3 级子级,如果ParentAccountId长度为 8,则它是第 4 级子级,然后ParentAccountId是长度为 11,然后它是第 5 级子级。由于第一级的孩子有 2 个长度的ParentAccountId那么后续的孩子将拥有ParentAccountId作为父母加Code。为了更好地理解,请参阅第二个,因为我的英语不是那么好。

我对逻辑感到困惑。有什么建议吗?

您可以使用reduce方法创建树结构来创建递归函数,在每次迭代中检查父 id 是否等于当前元素 id。

const data = [{"Id":"1","Code":"01","Title":"Account 01","ParentAccountId":null},{"Id":"2","Code":"02","Title":"Account 02","ParentAccountId":null},{"Id":"3","Code":"01001","Title":"Account 01001","ParentAccountId":"01"},{"Id":"4","Code":"01002","Title":"Account 01002","ParentAccountId":"01"},{"Id":"5","Code":"01002001","Title":"Account 01002001","ParentAccountId":"01002"}]
function toTree(data, pid = null) {
return data.reduce((r, e) => {
if (e.ParentAccountId == pid) {
const obj = { ...e };
const children = toTree(data, e.Code);
if (children.length) obj.children = children;
r.push(obj);
}
return r;
}, [])
}
const result = toTree(data)
console.log(result)

所涉及的逻辑是首先尝试查找每个对象的子对象(使用filter完成查找ParentAccountId等于每个对象的所有对象Code),然后过滤数据以仅返回根父级(ParentAccountId等于 null 的对象)。

请尝试下面的代码。

var data = [{
"Id": "1",
"Code": "01",
"Title": "Account 01",
"ParentAccountId": null
},
{
"Id": "2",
"Code": "02",
"Title": "Account 02",
"ParentAccountId": null
},
{
"Id": "3",
"Code": "01001",
"Title": "Account 01001",
"ParentAccountId": "01"
},
{
"Id": "4",
"Code": "01002",
"Title": "Account 01002",
"ParentAccountId": "01"
},
{
"Id": "5",
"Code": "01002001",
"Title": "Account 01002001",
"ParentAccountId": "01002"
}
]
rearrangeData = () => {
var newData = []
data.forEach((x) => {
x['children'] = data.filter((y) => {
return y.ParentAccountId === x.Code
})
var parent = data.find((y) => {
return y.Code === x.ParentAccountId
})
if (parent && parent.children) {
parent.children.push(x)
} else if (parent && !parent.children) {
parent['children'] = [x];
} else {
return x
}
newData.push(parent)
})
var parents = newData.filter((x) => {
return x.ParentAccountId === null
})
console.log(parents);
}
rearrangeData()

我在工作中等待一项任务,所以我想我会为你提供一个实现。并不是说它比链接线程中的解决方案更好或更差 - 只是另一种实现:

const data = [{
"Id": "1",
"Code": "01",
"Title": "Account 01",
"ParentAccountId": null
},
{
"Id": "2",
"Code": "02",
"Title": "Account 02",
"ParentAccountId": null
},
{
"Id": "3",
"Code": "01001",
"Title": "Account 01001",
"ParentAccountId": "01"
},
{
"Id": "4",
"Code": "01002",
"Title": "Account 01002",
"ParentAccountId": "01"
},
{
"Id": "5",
"Code": "01002001",
"Title": "Account 01002001",
"ParentAccountId": "01002"
}
]
function buildTree(obj) {
// get all top level parents
let parents = obj.filter((o) => !o.ParentAccountId);
// loop over the parents and recursively call addChild to populate the tree
parents.forEach((p) => {
p.children = addChildren(p, obj);
});
return parents;
}
function addChildren(parent, obj) {
// find all children for this parent
let children = obj.filter((o) => o.ParentAccountId === parent.Code)
if (children.length) {
// loop over any children recursively calling this function to add nested children
children.forEach((c) => {
c.children = addChildren(c, obj);
});
return children;
} else {
return [];
}
}
console.log(buildTree(data));

您可以遍历每个节点并构建子级 id 到子级的映射。

然后,再次遍历节点,但这次查看父 id,并将节点推送到父节点(如果它是子节点),或者将其添加到根列表中。此响应从此处改编,并添加了自定义密钥配置。

我还添加了一个方法来删除任何不包含子对象(即叶节点)上的children字段。

console.log(convertListToTree(getDataList(), {
idKey : 'Code',
parentIdKey : 'ParentAccountId',
pruneEmptyChildren : true
}));
function convertListToTree(list, options) {
options = Object.assign({
idKey : 'id',
parentIdKey : 'parentId',
childrenKey : 'children',
pruneEmptyChildren : false
}, options || {});
let map = {}, node, roots = [], i;
for (i = 0; i < list.length; i++) {
map[list[i][options.idKey]] = i;
list[i][options.childrenKey] = []; // Attach a "child" reference holder
}
for (i = 0; i < list.length; i++) {
node = list[i];
if (node[options.parentIdKey] != null) {
list[map[node[options.parentIdKey]]][options.childrenKey].push(node);
} else {
roots.push(node);
}
}
if (options.pruneEmptyChildren) {
pruneEmptyKeys(roots, options.childrenKey); // Remove empty
}
return roots;
}
function pruneEmptyKeys(tree, childKey) {
let items = tree[childKey] || tree;
items.forEach(item => {
if (item[childKey].length > 0) {
pruneEmptyKeys(item[childKey], childKey);
} else {
delete item[childKey]; // Remove empty child list
}
});
}
function getDataList() {
return [{
"Id": "1",
"Code": "01",
"Title": "Account 01",
"ParentAccountId": null
}, {
"Id": "2",
"Code": "02",
"Title": "Account 02",
"ParentAccountId": null
}, {
"Id": "3",
"Code": "01001",
"Title": "Account 01001",
"ParentAccountId": "01"
}, {
"Id": "4",
"Code": "01002",
"Title": "Account 01002",
"ParentAccountId": "01"
}, {
"Id": "5",
"Code": "01002001",
"Title": "Account 01002001",
"ParentAccountId": "01002"
}];
}
.as-console-wrapper {
top: 0;
max-height: 100% !important;
}
<!-- Adapted from: https://stackoverflow.com/a/18018037/1762224 -->

最新更新