根据一些键值 JavaScript 从 JSON 创建层次结构列表
Create a hierarchy list from an JSON based on some key values JavaScript
我收到了来自 BE 的 JSON:
[
{
"id": 51,
"name": null,
"parentAccountName": "test-name",
"parentAccountId": 50
},
{
"id": 87,
"name": null,
"parentAccountName": "nam1",
"parentAccountId": 83
},
{
"id": 86,
"name": null,
"parentAccountName": "nam1",
"parentAccountId": 83
},
{
"id": 85,
"name": null,
"parentAccountName": "Test andrei",
"parentAccountId": 37
},
{
"id": 84,
"name": "nam1",
"parentAccountName": "Test andrei",
"parentAccountId": 37
},
{
"id": 50,
"name": "test-name",
"parentAccountName": "nam1",
"parentAccountId": 83
},
{
"id": 37,
"name": "Test andrei",
"parentAccountName": "test-name",
"parentAccountId": 50
},
{
"id": 34,
"name": null,
"parentAccountName": "Test andrei",
"parentAccountId": 37
}
]
我需要根据 parentAccountId 创建帐户层次结构,规则是:检查列表中的每个条目是否有父级并分配给它,否则为创建该元素作为根元素并将其放在层次结构中的正确位置。
结果应该是:
[
{
parentAccountName: 'nam1',
parentAccountId: 83,
children: [
{
id: 50,
name: 'test-name',
parentAccountName: 'nam1',
parentAccountId: 83,
children: [
{
id: 37,
name: 'Test andrei',
parentAccountName: 'test-name',
parentAccountId: 50,
children: [
{
id: 85,
name: null,
parentAccountName: 'Test andrei',
parentAccountId: 37,
},
{
id: 84,
name: 'nam1',
parentAccountName: 'Test andrei',
parentAccountId: 37,
},
{
id: 34,
name: null,
parentAccountName: 'Test andrei',
parentAccountId: 37,
},
],
},
{
id: 51,
name: null,
parentAccountName: 'test-name',
parentAccountId: 50,
},
],
},
{
id: 87,
name: null,
parentAccountName: 'nam1',
parentAccountId: 83,
},
{
id: 86,
name: null,
parentAccountName: 'nam1',
parentAccountId: 83,
},
],
},
];
我尝试执行递归函数并通过 parentAcountId 检查,但我做错了。此外,从 BE 获得的格式也不是很清楚。我的解决方案是:
const loadLazyData = (): void => {
if (props.accounts) {
setAccountsHierarchy(configureHierarchyNodes(props.accounts, 0));
}
};
const configureHierarchyNodes = (hierarchy: IAccount[], parent?: number | undefined | null): TreeNode[] => {
const result = [];
for (const i in hierarchy) {
if (hierarchy[i].parentAccountId == parent) {
const children = configureHierarchyNodes(hierarchy, hierarchy[i].id);
if (children.length) {
hierarchy[i].children = children;
}
result.push({ ...hierarchy[i], key: `${i}-${hierarchy[i].id}`, label: hierarchy[i].accountDisplayName });
}
}
return result;
};
也许我遗漏了什么,但是在2天内我没有设法解决这个问题。如果有人有任何想法,我将不胜感激。提前致谢!
将数组缩减为Map,再转回数组,使用Array.filter()
得到所有不带parentAccountId
的节点属性。如果应该只有一个顶级父级,请改用 Array.find()
。
const arr = [{"id":51,"name":null,"parentAccountName":"test-name","parentAccountId":50},{"id":87,"name":null,"parentAccountName":"nam1","parentAccountId":83},{"id":86,"name":null,"parentAccountName":"nam1","parentAccountId":83},{"id":85,"name":null,"parentAccountName":"Test andrei","parentAccountId":37},{"id":84,"name":"nam1","parentAccountName":"Test andrei","parentAccountId":37},{"id":50,"name":"test-name","parentAccountName":"nam1","parentAccountId":83},{"id":37,"name":"Test andrei","parentAccountName":"test-name","parentAccountId":50},{"id":34,"name":null,"parentAccountName":"Test andrei","parentAccountId":37}]
const result = Array.from(
arr.reduce((acc, o) => {
const { parentAccountId: id, parentAccountName: name } = o
if(!acc.has(id)) acc.set(id, { id, name }) // if the current item's parent doesn't exist, create it in the Map
const parent = acc.get(id) // get the current parent
parent.children ??= [] // init children if it doesn't exist
if(!acc.has(o.id)) acc.set(o.id, o) // add the current item to the Map if it doesn't exist
else Object.assign(acc.get(o.id), o) // combine it with the existing object if it does
parent.children.push(acc.get(o.id)) // add the item to the children
return acc
}, new Map()).values()
).filter(o => !o.hasOwnProperty('parentAccountId'))
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以采用标准算法来创建树。
结果拿走了没有自己的object的parents。
const
getTree = (data, id, parent) => {
const
t = {},
parents = new Set,
children = new Set;
data.forEach(o => {
parents.add(o[parent]);
children.add(o[id]);
((t[o[parent]] ??= { [id]: o[parent] }).children ??= []).push(Object.assign(t[o[id]] ??= {}, o))
});
children.forEach(Set.prototype.delete, parents);
return [...parents].map(id => t[id]);
},
data = [{ id: 51, name: null, parentAccountName: "test-name", parentAccountId: 50 }, { id: 87, name: null, parentAccountName: "nam1", parentAccountId: 83 }, { id: 86, name: null, parentAccountName: "nam1", parentAccountId: 83 }, { id: 85, name: null, parentAccountName: "Test andrei", parentAccountId: 37 }, { id: 84, name: "nam1", parentAccountName: "Test andrei", parentAccountId: 37 }, { id: 50, name: "test-name", parentAccountName: "nam1", parentAccountId: 83 }, { id: 37, name: "Test andrei", parentAccountName: "test-name", parentAccountId: 50 }, { id: 34, name: null, parentAccountName: "Test andrei", parentAccountId: 37 }],
tree = getTree(data, 'id', 'parentAccountId');
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我收到了来自 BE 的 JSON:
[
{
"id": 51,
"name": null,
"parentAccountName": "test-name",
"parentAccountId": 50
},
{
"id": 87,
"name": null,
"parentAccountName": "nam1",
"parentAccountId": 83
},
{
"id": 86,
"name": null,
"parentAccountName": "nam1",
"parentAccountId": 83
},
{
"id": 85,
"name": null,
"parentAccountName": "Test andrei",
"parentAccountId": 37
},
{
"id": 84,
"name": "nam1",
"parentAccountName": "Test andrei",
"parentAccountId": 37
},
{
"id": 50,
"name": "test-name",
"parentAccountName": "nam1",
"parentAccountId": 83
},
{
"id": 37,
"name": "Test andrei",
"parentAccountName": "test-name",
"parentAccountId": 50
},
{
"id": 34,
"name": null,
"parentAccountName": "Test andrei",
"parentAccountId": 37
}
]
我需要根据 parentAccountId 创建帐户层次结构,规则是:检查列表中的每个条目是否有父级并分配给它,否则为创建该元素作为根元素并将其放在层次结构中的正确位置。 结果应该是:
[
{
parentAccountName: 'nam1',
parentAccountId: 83,
children: [
{
id: 50,
name: 'test-name',
parentAccountName: 'nam1',
parentAccountId: 83,
children: [
{
id: 37,
name: 'Test andrei',
parentAccountName: 'test-name',
parentAccountId: 50,
children: [
{
id: 85,
name: null,
parentAccountName: 'Test andrei',
parentAccountId: 37,
},
{
id: 84,
name: 'nam1',
parentAccountName: 'Test andrei',
parentAccountId: 37,
},
{
id: 34,
name: null,
parentAccountName: 'Test andrei',
parentAccountId: 37,
},
],
},
{
id: 51,
name: null,
parentAccountName: 'test-name',
parentAccountId: 50,
},
],
},
{
id: 87,
name: null,
parentAccountName: 'nam1',
parentAccountId: 83,
},
{
id: 86,
name: null,
parentAccountName: 'nam1',
parentAccountId: 83,
},
],
},
];
我尝试执行递归函数并通过 parentAcountId 检查,但我做错了。此外,从 BE 获得的格式也不是很清楚。我的解决方案是:
const loadLazyData = (): void => {
if (props.accounts) {
setAccountsHierarchy(configureHierarchyNodes(props.accounts, 0));
}
};
const configureHierarchyNodes = (hierarchy: IAccount[], parent?: number | undefined | null): TreeNode[] => {
const result = [];
for (const i in hierarchy) {
if (hierarchy[i].parentAccountId == parent) {
const children = configureHierarchyNodes(hierarchy, hierarchy[i].id);
if (children.length) {
hierarchy[i].children = children;
}
result.push({ ...hierarchy[i], key: `${i}-${hierarchy[i].id}`, label: hierarchy[i].accountDisplayName });
}
}
return result;
};
也许我遗漏了什么,但是在2天内我没有设法解决这个问题。如果有人有任何想法,我将不胜感激。提前致谢!
将数组缩减为Map,再转回数组,使用Array.filter()
得到所有不带parentAccountId
的节点属性。如果应该只有一个顶级父级,请改用 Array.find()
。
const arr = [{"id":51,"name":null,"parentAccountName":"test-name","parentAccountId":50},{"id":87,"name":null,"parentAccountName":"nam1","parentAccountId":83},{"id":86,"name":null,"parentAccountName":"nam1","parentAccountId":83},{"id":85,"name":null,"parentAccountName":"Test andrei","parentAccountId":37},{"id":84,"name":"nam1","parentAccountName":"Test andrei","parentAccountId":37},{"id":50,"name":"test-name","parentAccountName":"nam1","parentAccountId":83},{"id":37,"name":"Test andrei","parentAccountName":"test-name","parentAccountId":50},{"id":34,"name":null,"parentAccountName":"Test andrei","parentAccountId":37}]
const result = Array.from(
arr.reduce((acc, o) => {
const { parentAccountId: id, parentAccountName: name } = o
if(!acc.has(id)) acc.set(id, { id, name }) // if the current item's parent doesn't exist, create it in the Map
const parent = acc.get(id) // get the current parent
parent.children ??= [] // init children if it doesn't exist
if(!acc.has(o.id)) acc.set(o.id, o) // add the current item to the Map if it doesn't exist
else Object.assign(acc.get(o.id), o) // combine it with the existing object if it does
parent.children.push(acc.get(o.id)) // add the item to the children
return acc
}, new Map()).values()
).filter(o => !o.hasOwnProperty('parentAccountId'))
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以采用标准算法来创建树。
结果拿走了没有自己的object的parents。
const
getTree = (data, id, parent) => {
const
t = {},
parents = new Set,
children = new Set;
data.forEach(o => {
parents.add(o[parent]);
children.add(o[id]);
((t[o[parent]] ??= { [id]: o[parent] }).children ??= []).push(Object.assign(t[o[id]] ??= {}, o))
});
children.forEach(Set.prototype.delete, parents);
return [...parents].map(id => t[id]);
},
data = [{ id: 51, name: null, parentAccountName: "test-name", parentAccountId: 50 }, { id: 87, name: null, parentAccountName: "nam1", parentAccountId: 83 }, { id: 86, name: null, parentAccountName: "nam1", parentAccountId: 83 }, { id: 85, name: null, parentAccountName: "Test andrei", parentAccountId: 37 }, { id: 84, name: "nam1", parentAccountName: "Test andrei", parentAccountId: 37 }, { id: 50, name: "test-name", parentAccountName: "nam1", parentAccountId: 83 }, { id: 37, name: "Test andrei", parentAccountName: "test-name", parentAccountId: 50 }, { id: 34, name: null, parentAccountName: "Test andrei", parentAccountId: 37 }],
tree = getTree(data, 'id', 'parentAccountId');
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }