英文:
Take a JSON in JS and create the nested children based on two keys
问题
我正在尝试将一个扁平的JSON文件转化为一个结构化的树,将具有匹配NodeID的ParentID的相关子项放置在相应的NodeID下面。
但是,如果没有ParentID,它应该查看previousSiblingId并将记录放置在相应的NodeID下面。
我认为我已经接近了,我能够使它在parentId上工作,但当我引入previousSiblingId时,它停止工作。
这是初始的扁平文件:
期望的结果应该是:
[
{
"nodeId": "3",
"name": "Three",
"parentId": null,
"previousSiblingId": null,
"children": []
},
{
"nodeId": "1",
"name": "One",
"parentId": null,
"previousSiblingId": "3",
"children": [
{
"nodeId": "2",
"name": "Two",
"parentId": "1",
"previousSiblingId": null,
"children": [
{
"nodeId": "6",
"name": "Six",
"parentId": "2",
"previousSiblingId": null,
"children": []
},
{
"nodeId": "4",
"name": "Four",
"parentId": "2",
"previousSiblingId": "6",
"children": [
{
"nodeId": "5",
"name": "Five",
"parentId": "4",
"previousSiblingId": null,
"children": []
}
]
}
]
}
]
},
{
"nodeId": "7",
"name": "Seven",
"parentId": null,
"previousSiblingId": "1",
"children": [
{
"nodeId": "8",
"name": "Eight",
"parentId": "7",
"previousSiblingId": null,
"children": []
}
]
}
]
我的当前结果是:
[
{
"nodeId": "3",
"name": "Three",
"parentId": null,
"previousSiblingId": null,
"children": []
},
{
"nodeId": "7",
"name": "Seven",
"parentId": null,
"previousSiblingId": "1",
"children": [
{
"nodeId": "8",
"name": "Eight",
"parentId": "7",
"previousSiblingId": null,
"children": []
}
]
},
{
"nodeId": "1",
"name": "One",
"parentId": null,
"previousSiblingId": "3",
"children": [
{
"nodeId": "2",
"name": "Two",
"parentId": "1",
"previousSiblingId": null,
"children": [
{
"nodeId": "4",
"name": "Four",
"parentId": "2",
"previousSiblingId": "6",
"children": [
{
"nodeId": "5",
"name": "Five",
"parentId": "4",
"previousSiblingId": null,
"children": []
}
]
},
{
"nodeId": "6",
"name": "Six",
"parentId": "2",
"previousSiblingId": null,
"children": []
}
]
}
]
}
]
我漏掉了什么?
英文:
I am taking a flat JSON file and trying to create a structured tree which places the relevant children, whose ParentID matches a NodeID, underneath the relevant NodeID.
However, if there is no parentID, it should look at the previousSiblingId and place the record underneath the relevant NodeID.
I believe I am close, I am able to make it work on the parentId but when I introduce the previousSiblingId it stops working.
This is the initial flat file:
The expected result should be:
[
{
"nodeId": "3",
"name": "Three",
"parentId": null,
"previousSiblingId": null,
"children": []
},
{
"nodeId": "1",
"name": "One",
"parentId": null,
"previousSiblingId": "3",
"children": [
{
"nodeId": "2",
"name": "Two",
"parentId": "1",
"previousSiblingId": null,
"children": [
{
"nodeId": "6",
"name": "Six",
"parentId": "2",
"previousSiblingId": null,
"children": []
},
{
"nodeId": "4",
"name": "Four",
"parentId": "2",
"previousSiblingId": "6",
"children": [
{
"nodeId": "5",
"name": "Five",
"parentId": "4",
"previousSiblingId": null,
"children": []
}
]
}
]
}
]
},
{
"nodeId": "7",
"name": "Seven",
"parentId": null,
"previousSiblingId": "1",
"children": [
{
"nodeId": "8",
"name": "Eight",
"parentId": "7",
"previousSiblingId": null,
"children": []
}
]
}
]
my current result is:
[
{
"nodeId": "3",
"name": "Three",
"parentId": null,
"previousSiblingId": null,
"children": []
},
{
"nodeId": "7",
"name": "Seven",
"parentId": null,
"previousSiblingId": "1",
"children": [
{
"nodeId": "8",
"name": "Eight",
"parentId": "7",
"previousSiblingId": null,
"children": []
}
]
},
{
"nodeId": "1",
"name": "One",
"parentId": null,
"previousSiblingId": "3",
"children": [
{
"nodeId": "2",
"name": "Two",
"parentId": "1",
"previousSiblingId": null,
"children": [
{
"nodeId": "4",
"name": "Four",
"parentId": "2",
"previousSiblingId": "6",
"children": [
{
"nodeId": "5",
"name": "Five",
"parentId": "4",
"previousSiblingId": null,
"children": []
}
]
},
{
"nodeId": "6",
"name": "Six",
"parentId": "2",
"previousSiblingId": null,
"children": []
}
]
}
]
}
]
What have I missed?
<html>
<pre id="json"></pre>
<script type="text/javascript">
const data = [{
"nodeId": "4",
"name": "Four",
"parentId": "2",
"previousSiblingId": "6"
},
{
"nodeId": "8",
"name": "Eight",
"parentId": "7",
"previousSiblingId": null
},
{
"nodeId": "2",
"name": "Two",
"parentId": "1",
"previousSiblingId": null
},
{
"nodeId": "6",
"name": "Six",
"parentId": "2",
"previousSiblingId": null
},
{
"nodeId": "3",
"name": "Three",
"parentId": null,
"previousSiblingId": null
},
{
"nodeId": "5",
"name": "Five",
"parentId": "4",
"previousSiblingId": null
},
{
"nodeId": "7",
"name": "Seven",
"parentId": null,
"previousSiblingId": "1"
},
{
"nodeId": "1",
"name": "One",
"parentId": null,
"previousSiblingId": "3"
}
];
const getParentDeep = (arr, targetId) => arr.find(({ nodeId }) => nodeId === targetId)
?? arr.flatMap(({ children }) => getParentDeep(children, targetId))
.filter(e => e)
.at(0);
const result = data
.sort(({ parentId: a }, { parentId: b }) => a - b, ({ previousSiblingId: c }, { previousSiblingId: d }) => c - d)
.reduce((acc, { nodeId, name, parentId, previousSiblingId }) => {
const obj = { nodeId, name: name, parentId: parentId, previousSiblingId: previousSiblingId, children: [] };
const parentObj = getParentDeep(acc, parentId);
const previousSiblingObj = getParentDeep(acc, previousSiblingId);
if (parentObj) parentObj.children.push(obj)
else
if (previousSiblingObj) previousSiblingObj.children.push(obj);
else
acc.push(obj);
return acc;
}, []);
//
console.log(result);
//Output the new JSON to the screen
document.getElementById("json").textContent = JSON.stringify(result, undefined, 2);
</script>
</html>
答案1
得分: 1
你可以使用一个对象采用单循环方法,将所有引用与子代和父代相关联。最后只获取具有 null
值作为父级的子代。
如果子代包含超过两个项目,对该数组进行排序。
const
data = [{ nodeId: "4", name: "Four", parentId: "2", previousSiblingId: "6" }, { nodeId: "8", name: "Eight", parentId: "7", previousSiblingId: null }, { nodeId: "2", name: "Two", parentId: "1", previousSiblingId: null }, { nodeId: "6", name: "Six", parentId: "2", previousSiblingId: null }, { nodeId: "3", name: "Three", parentId: null, previousSiblingId: null }, { nodeId: "5", name: "Five", parentId: "4", previousSiblingId: null }, { nodeId: "7", name: "Seven", parentId: null, previousSiblingId: "1" }, { nodeId: "1", name: "One", parentId: null, previousSiblingId: "3" }],
tree = function (data, root) {
const
sort = array => {
if (array.length < 2) return;
let node = array.find(o => o.previousSiblingId === null)?.nodeId,
i = 0;
while (i < array.length) {
if (array[i].nodeId !== node) {
const j = array.findIndex(o => o.nodeId === node);
array.splice(i, 0, ...array.splice(j, 1));
}
node = next[node];
i++;
}
},
empty = { nodeId: undefined, name: undefined, parentId: undefined, previousSiblingId: undefined },
next = {},
t = {};
data.forEach(o => {
Object.assign(t[o.nodeId] = t[o.nodeId] || { ...empty }, o);
t[o.parentId] ??= { ...empty };
t[o.parentId].children ??= [];
t[o.parentId].children.push(t[o.nodeId]);
if (o.previousSiblingId !== null) next[o.previousSiblingId] = o.nodeId;
sort(t[o.parentId].children);
});
return t[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
英文:
You could take a single loop approach with an object to keep all references with part to children and children to parent. At the end take only the children which have null
value as parent.
If child contains more than two items sort this array.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const
data = [{ nodeId: "4", name: "Four", parentId: "2", previousSiblingId: "6" }, { nodeId: "8", name: "Eight", parentId: "7", previousSiblingId: null }, { nodeId: "2", name: "Two", parentId: "1", previousSiblingId: null }, { nodeId: "6", name: "Six", parentId: "2", previousSiblingId: null }, { nodeId: "3", name: "Three", parentId: null, previousSiblingId: null }, { nodeId: "5", name: "Five", parentId: "4", previousSiblingId: null }, { nodeId: "7", name: "Seven", parentId: null, previousSiblingId: "1" }, { nodeId: "1", name: "One", parentId: null, previousSiblingId: "3" }],
tree = function (data, root) {
const
sort = array => {
if (array.length < 2) return;
let node = array.find(o => o.previousSiblingId === null)?.nodeId,
i = 0;
while (i < array.length) {
if (array[i].nodeId !== node) {
const j = array.findIndex(o => o.nodeId === node);
array.splice(i, 0, ...array.splice(j, 1));
}
node = next[node];
i++;
}
},
empty = { nodeId: undefined, name: undefined, parentId: undefined, previousSiblingId: undefined },
next = {},
t = {};
data.forEach(o => {
Object.assign(t[o.nodeId] = t[o.nodeId] || { ...empty }, o);
t[o.parentId] ??= { ...empty };
t[o.parentId].children ??= [];
t[o.parentId].children.push(t[o.nodeId]);
if (o.previousSiblingId !== null) next[o.previousSiblingId] = o.nodeId;
sort(t[o.parentId].children);
});
return t[root].children;
}(data, null);
console.log(tree);
<!-- language: lang-css -->
.as-console-wrapper { max-height: 100% !important; top: 0; }
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论