我有一个扁平的对象结构,该结构概述了哪些对象具有父对象,哪些对象没有父对象。现在,我需要将其格式化为正确的结构,以便可以循环浏览并执行功能。
只需添加,然后再进行详细说明。.我知道对象结构不一致,我仍在努力确保所有单个项目都一致。最重要的是孩子要与父母结盟。
我在网上搜索过,但似乎找不到符合我确切需要的任何内容。无论现在好坏,这种结构都是我现在所坚持的。
我对这段代码不满意,它会循环并将子代追加到适当的父代,并删除旧密钥。在这种特定情况下,我忘记了递归,也无法解决这个问题。
var tree = hierarchy.tree, key;
for (key in tree) {
if (tree.hasOwnProperty(key)) tree[key].children = {};
}
iterate();
return tree;
function iterate() {
var field, node;
for (field in tree) {
if (tree.hasOwnProperty(field)) {
node = tree[field];
if (node.parent !== undefined) {
tree[node.parent].children[field] = node;
delete tree[field];
}
}
}
}
这是基本结构:
var tree = {
"submit": {
"order": 0,
"field": "submit"
},
"hc3qu2nf4": {
"label": "title",
"parent": "",
"order": 0,
"field": "title",
"options": {
"Font Size": "25px",
"Font Weight": "Bold",
"Font Style": "Italic",
"Color": "rgb(64, 128, 128)"
}
},
"dhthivju9": {
"label": "divider",
"parent": "",
"order": 1,
"field": "divider",
"options": {
"height": "14px",
"color": "#21ce09",
"width": "50%"
}
},
"z5o9m7sgx": {
"label": "",
"parent": "4hhsi94n7",
"order": 0,
"field": "col"
},
"85ugwci2c": {
"label": "",
"parent": "4hhsi94n7",
"order": 1,
"field": "col"
},
"4hhsi94n7": {
"label": "column",
"parent": "",
"order": 2,
"field": "column"
},
"sbf0bg1o7": {
"label": "month",
"parent": "z5o9m7sgx",
"order": 0,
"field": "month",
"options": {
"start": "2019-04"
},
"required": true
},
"c3bwnyjmg": {
"label": "",
"parent": "4hhsi94n7",
"order": 2
},
"n5m9d84dg": {
"label": "number",
"parent": "85ugwci2c",
"order": 0,
"field": "number",
"options": {
"start": "5",
"min": "5",
"max": "10",
"step": "2"
}
},
"krfxfnzsr": {
"label": "date",
"parent": "c3bwnyjmg",
"order": 0,
"field": "date",
"options": {
"start": "2019-05-03"
}
}
}
理想情况下,我希望结构如下。可能会有比这更多的层。
{
"submit": {
"order": 0,
"field": "submit"
},
"hc3qu2nf4": {
"label": "title",
"parent": "",
"order": 0,
"field": "title",
"options": {
"Font Size": "25px",
"Font Weight": "Bold",
"Font Style": "Italic",
"Color": "rgb(64, 128, 128)"
}
},
"dhthivju9": {
"label": "divider",
"parent": "",
"order": 1,
"field": "divider",
"options": {
"height": "14px",
"color": "#21ce09",
"width": "50%"
}
},
"4hhsi94n7": {
"label": "column",
"parent": "",
"order": 2,
"field": "column",
"children": {
"z5o9m7sgx": {
"label": "",
"order": 0,
"field": "col",
"children": {
"sbf0bg1o7": {
"label": "month",
"parent": "z5o9m7sgx",
"order": 0,
"field": "month",
"options": {
"start": "2019-04"
},
"required": true
}
}
},
"85ugwci2c": {
"label": "",
"order": 1,
"field": "col",
"children": {
"n5m9d84dg": {
"label": "number",
"parent": "85ugwci2c",
"order": 0,
"field": "number",
"options": {
"start": "5",
"min": "5",
"max": "10",
"step": "2"
}
}
}
},
"c3bwnyjmg": {
"label": "",
"order": 2,
"children": {
"krfxfnzsr": {
"label": "date",
"parent": "c3bwnyjmg",
"order": 0,
"field": "date",
"options": {
"start": "2019-05-03"
}
}
}
}
}
}
}
此外,如果我能保持每个项目的适当“顺序”,那么对它们进行适当的排序也可能很棒。
更新 我不喜欢输出结构。如果有人有更好的主意,请告诉我。
答案 0 :(得分:0)
我找到了这个解决方案,但是它使用数组而不是对象(对于find
,reduce
,splice
,push
等),因此最终输出为并非完全符合您的要求,但您写的内容并非一成不变。
const data = {
"submit": {
"order": 0,
"field": "submit"
},
"hc3qu2nf4": {
"label": "title",
"parent": "",
"order": 0,
"field": "title",
"options": {
"Font Size": "25px",
"Font Weight": "Bold",
"Font Style": "Italic",
"Color": "rgb(64, 128, 128)"
}
},
"dhthivju9": {
"label": "divider",
"parent": "",
"order": 1,
"field": "divider",
"options": {
"height": "14px",
"color": "#21ce09",
"width": "50%"
}
},
"z5o9m7sgx": {
"label": "",
"parent": "4hhsi94n7",
"order": 0,
"field": "col"
},
"85ugwci2c": {
"label": "",
"parent": "4hhsi94n7",
"order": 1,
"field": "col"
},
"4hhsi94n7": {
"label": "column",
"parent": "",
"order": 2,
"field": "column"
},
"sbf0bg1o7": {
"label": "month",
"parent": "z5o9m7sgx",
"order": 0,
"field": "month",
"options": {
"start": "2019-04"
},
"required": true
},
"c3bwnyjmg": {
"label": "",
"parent": "4hhsi94n7",
"order": 2
},
"n5m9d84dg": {
"label": "number",
"parent": "85ugwci2c",
"order": 0,
"field": "number",
"options": {
"start": "5",
"min": "5",
"max": "10",
"step": "2"
}
},
"krfxfnzsr": {
"label": "date",
"parent": "c3bwnyjmg",
"order": 0,
"field": "date",
"options": {
"start": "2019-05-03"
}
}
};
function sortArray(orderedArray, remainingArray) {
if(remainingArray.length === 0) {
return orderedArray;
}
else {
remainingArray.forEach((remainingItem, index) => {
if(orderedArray.find(x => x.identifier === remainingItem.parent)) {
orderedArray.push(remainingItem);
remainingArray.splice(index, 1);
}
});
return sortArray(orderedArray, remainingArray);
}
}
function insertNode(tree, node) {
if(!tree) return;
let item = tree.find(x => x.identifier === node.parent);
if(item) {
(item.children || (item.children = [])).push(node);
} else {
tree.forEach(x => {
insertNode(x.children, node);
});
}
return tree;
}
function createTree(data) {
let tempArray = [];
for (let key in data) {
tempArray.push({ ...data[key], identifier: key });
}
tempArray = sortArray(tempArray.filter(x => !x.parent), tempArray.filter(x => x.parent));
return tempArray.reduce((accumulator, currentValue) => {
if(currentValue.parent === "") {
accumulator.push(currentValue);
} else {
insertNode(accumulator, currentValue);
}
return accumulator;
}, []);
}
console.log(createTree(data));
答案 1 :(得分:0)
下面的示例保留Object
类型,而不是切换到Array
。有关更多详细信息,请参见内联注释。基本概念是将树本身视为主分支,并在分支中进行迭代,直到找到父级以将子级重新定位到该子级。
//iterating through an object/array that's changing can cause unexpected results
//iterate through a duplicate that will not change
let tree = {
"submit": {
"order": 0,
"field": "submit"
},
"hc3qu2nf4": {
"label": "title",
"parent": "",
"order": 0,
"field": "title",
"options": {
"Font Size": "25px",
"Font Weight": "Bold",
"Font Style": "Italic",
"Color": "rgb(64, 128, 128)"
}
},
"dhthivju9": {
"label": "divider",
"parent": "",
"order": 1,
"field": "divider",
"options": {
"height": "14px",
"color": "#21ce09",
"width": "50%"
}
},
"z5o9m7sgx": {
"label": "",
"parent": "4hhsi94n7",
"order": 0,
"field": "col"
},
"85ugwci2c": {
"label": "",
"parent": "4hhsi94n7",
"order": 1,
"field": "col"
},
"4hhsi94n7": {
"label": "column",
"parent": "",
"order": 2,
"field": "column"
},
"sbf0bg1o7": {
"label": "month",
"parent": "z5o9m7sgx",
"order": 0,
"field": "month",
"options": {
"start": "2019-04"
},
"required": true
},
"c3bwnyjmg": {
"label": "",
"parent": "4hhsi94n7",
"order": 2
},
"n5m9d84dg": {
"label": "number",
"parent": "85ugwci2c",
"order": 0,
"field": "number",
"options": {
"start": "5",
"min": "5",
"max": "10",
"step": "2"
}
},
"krfxfnzsr": {
"label": "date",
"parent": "c3bwnyjmg",
"order": 0,
"field": "date",
"options": {
"start": "2019-05-03"
}
}
},
tree2 = JSON.parse(JSON.stringify(tree)); //clone, not reference
console.log(tree === tree2); //test to confirm duplicate is not a reference
function reposition_child(parent, child, node, branch) {
//check if the parent exists in this branch
if (branch.hasOwnProperty(parent)) {
let bp = branch[parent];
//create children object as needed
if (!bp.hasOwnProperty('children')) {
bp.children = {};
}
//transplant the node as a child
bp.children[child] = node;
return true;
} else {
//iterate through the branches with children looking for the parent
let found = false;
for (let sub_branch in branch) {
if (branch[sub_branch].hasOwnProperty('children')) {
found = reposition_child(parent, child, node, branch[sub_branch].children);
}
//exit the loop once the parent is found
if (found) {
return true;
}
}
}
return false;
}
//iterate through the tree (duplicate fixed version)
for (let node in tree2) {
let tn = tree2[node];
//reposition nodes that have a non-empty parent
if (tn.hasOwnProperty('parent') && tn.parent.length) {
reposition_child(tn.parent, node, tn, tree);
delete tree[node];
}
}
//cleanup and output
delete tree2;
console.log(tree);