压扁一棵 JavaScript 树,尝试了一些解决方案
Flatten a JavaScript tree, tried some solutions
给定这棵树,是否有一种简单的方法可以将其转换为具有以下条件的平面数组?
- JS ES5,jQuery 也用过
- 尊重呈现顺序
- 添加一个"level" 属性表示缩进级别,从0
开始
[
{
"root": "0",
"id": "1",
"name": "Frutta",
"status": "1",
"position": "1",
"children": [
{
"root": "1",
"id": "4",
"name": "Agrumi",
"status": "1",
"position": "3",
"children": []
},
{
"root": "1",
"id": "5",
"name": "Pere",
"status": "1",
"position": "4",
"children": []
}
]
},
{
"root": "0",
"id": "2",
"name": "Ortaggi",
"status": "1",
"position": "1",
"children": [
{
"root": "2",
"id": "7",
"name": "Da foglia",
"status": "1",
"position": "6",
"children": [
{
"root": "7",
"id": "9",
"name": "Insalate",
"status": "1",
"position": "1",
"children": []
}
]
},
{
"root": "2",
"id": "8",
"name": "Da fiore",
"status": "1",
"position": "7",
"children": []
},
{
"root": "2",
"id": "21",
"name": "Da frutto",
"status": "1",
"position": "16",
"children": []
},
{
"root": "2",
"id": "22",
"name": "Da radici",
"status": "1",
"position": "17",
"children": []
},
{
"root": "2",
"id": "23",
"name": "Da fusto",
"status": "1",
"position": "8",
"children": []
},
{
"root": "2",
"id": "24",
"name": "Da bulbi",
"status": "1",
"position": "18",
"children": []
}
]
},
{
"root": "0",
"id": "15",
"name": "Colori",
"status": "1",
"position": "14",
"children": [
{
"root": "15",
"id": "3",
"name": "Banane",
"status": "1",
"position": "2",
"children": [
{
"root": "3",
"id": "6",
"name": "Mele",
"status": "1",
"position": "5",
"children": []
}
]
},
{
"root": "15",
"id": "16",
"name": "Blu/Viola",
"status": "1",
"position": "10",
"children": []
},
{
"root": "15",
"id": "17",
"name": "Verde",
"status": "1",
"position": "11",
"children": []
},
{
"root": "15",
"id": "18",
"name": "Bianco",
"status": "1",
"position": "12",
"children": []
},
{
"root": "15",
"id": "19",
"name": "Giallo/Arancio",
"status": "1",
"position": "13",
"children": []
},
{
"root": "15",
"id": "20",
"name": "Rosso",
"status": "1",
"position": "14",
"children": []
}
]
},
{
"root": "0",
"id": "25",
"name": "Persone",
"status": "1",
"position": "24",
"children": [
{
"root": "25",
"id": "26",
"name": "Fabrizio",
"status": "1",
"position": "2",
"children": [
{
"root": "26",
"id": "27",
"name": "Uomo",
"status": "1",
"position": "21",
"children": []
}
]
},
{
"root": "25",
"id": "28",
"name": "Ivan",
"status": "1",
"position": "1",
"children": []
}
]
},
{
"root": "0",
"id": "29",
"name": "Category",
"status": "1",
"position": "25",
"children": []
}
]
预期的结果应该是这样的:
[
{
"root": "0",
"id": "1",
"name": "Frutta",
"status": "1",
"position": "1"
"level": 0
},
{
"root": "1",
"id": "4",
"name": "Agrumi",
"status": "1",
"position": "3",
"level": 1
},
{
"root": "1",
"id": "5",
"name": "Pere",
"status": "1",
"position": "4",
"level": 1
},
{
"root": "0",
"id": "2",
"name": "Ortaggi",
"status": "1",
"position": "1",
"level": 0
},
{
"root": "2",
"id": "7",
"name": "Da foglia",
"status": "1",
"position": "6",
"level": 1
},
{
"root": "7",
"id": "9",
"name": "Insalate",
"status": "1",
"position": "1",
"level": 2
},
...
我找到了这个函数,但有一些缺点:
var flattenTree = function(treeObj, idAttr, parentAttr, childrenAttr, levelAttr) {
if (!idAttr) idAttr = 'id';
if (!parentAttr) parentAttr = 'root';
if (!childrenAttr) childrenAttr = 'children';
if (!levelAttr) levelAttr = 'level';
function flattenChild(childObj, parentId, level) {
var array = [];
var childCopy = $.extend({}, childObj);
childCopy[levelAttr] = level;
childCopy[parentAttr] = parentId || "0";
delete childCopy[childrenAttr];
array.push(childCopy);
array = array.concat(processChildren(childObj, level));
return array;
};
function processChildren(obj, level) {
if (!level) level = 0;
var array = [];
obj[childrenAttr].forEach(function(childObj) {
array = array.concat(flattenChild(childObj, obj[idAttr], level+1));
});
return array;
};
var result = processChildren(treeObj);
return result;
};
- 我应该首先构建另一个以 "children" 开头的数组作为根
[
"children": <my original array here>
]
- 级别从 1 开始,而不是 0(我尝试输入
level = -1
但没有成功)
这是一个有效的 fiddle:https://jsfiddle.net/yLke452z/
谢谢
您可以对 Array#flatMap
采取递归方法并存储下一次调用的级别。
const
flatTree = (level = 0) => ({ children = [], ...object }) => [
{ ...object, level }, ...children.flatMap(flatTree(level + 1))
];
var tree = [{ root: "0", id: "1", name: "Frutta", status: "1", position: "1", children: [{ root: "1", id: "4", name: "Agrumi", status: "1", position: "3", children: [] }, { root: "1", id: "5", name: "Pere", status: "1", position: "4", children: [] }] }, { root: "0", id: "2", name: "Ortaggi", status: "1", position: "1", children: [{ root: "2", id: "7", name: "Da foglia", status: "1", position: "6", children: [{ root: "7", id: "9", name: "Insalate", status: "1", position: "1", children: [] }] }, { root: "2", id: "8", name: "Da fiore", status: "1", position: "7", children: [] }, { root: "2", id: "21", name: "Da frutto", status: "1", position: "16", children: [] }, { root: "2", id: "22", name: "Da radici", status: "1", position: "17", children: [] }, { root: "2", id: "23", name: "Da fusto", status: "1", position: "8", children: [] }, { root: "2", id: "24", name: "Da bulbi", status: "1", position: "18", children: [] }] }, { root: "0", id: "15", name: "Colori", status: "1", position: "14", children: [{ root: "15", id: "3", name: "Banane", status: "1", position: "2", children: [{ root: "3", id: "6", name: "Mele", status: "1", position: "5", children: [] }] }, { root: "15", id: "16", name: "Blu/Viola", status: "1", position: "10", children: [] }, { root: "15", id: "17", name: "Verde", status: "1", position: "11", children: [] }, { root: "15", id: "18", name: "Bianco", status: "1", position: "12", children: [] }, { root: "15", id: "19", name: "Giallo/Arancio", status: "1", position: "13", children: [] }, { root: "15", id: "20", name: "Rosso", status: "1", position: "14", children: [] }] }, { root: "0", id: "25", name: "Persone", status: "1", position: "24", children: [{ root: "25", id: "26", name: "Fabrizio", status: "1", position: "2", children: [{ root: "26", id: "27", name: "Uomo", status: "1", position: "21", children: [] }] }, { root: "25", id: "28", name: "Ivan", status: "1", position: "1", children: [] }] }, { root: "0", id: "29", name: "Category", status: "1", position: "25", children: [] }],
flat = tree.flatMap(flatTree());
console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES5 与 Array#reduce
.
function flatTree(level) {
return function(result, object) {
var children = object.children || [],
item = Object.keys(object).reduce(function (o, k) {
if (k !== 'children') o[k] = object[k];
return o;
}, {});
level = level || 0;
item.level = level;
return result.concat(item, children.reduce(flatTree(level + 1), []));
};
}
var tree = [{ root: "0", id: "1", name: "Frutta", status: "1", position: "1", children: [{ root: "1", id: "4", name: "Agrumi", status: "1", position: "3", children: [] }, { root: "1", id: "5", name: "Pere", status: "1", position: "4", children: [] }] }, { root: "0", id: "2", name: "Ortaggi", status: "1", position: "1", children: [{ root: "2", id: "7", name: "Da foglia", status: "1", position: "6", children: [{ root: "7", id: "9", name: "Insalate", status: "1", position: "1", children: [] }] }, { root: "2", id: "8", name: "Da fiore", status: "1", position: "7", children: [] }, { root: "2", id: "21", name: "Da frutto", status: "1", position: "16", children: [] }, { root: "2", id: "22", name: "Da radici", status: "1", position: "17", children: [] }, { root: "2", id: "23", name: "Da fusto", status: "1", position: "8", children: [] }, { root: "2", id: "24", name: "Da bulbi", status: "1", position: "18", children: [] }] }, { root: "0", id: "15", name: "Colori", status: "1", position: "14", children: [{ root: "15", id: "3", name: "Banane", status: "1", position: "2", children: [{ root: "3", id: "6", name: "Mele", status: "1", position: "5", children: [] }] }, { root: "15", id: "16", name: "Blu/Viola", status: "1", position: "10", children: [] }, { root: "15", id: "17", name: "Verde", status: "1", position: "11", children: [] }, { root: "15", id: "18", name: "Bianco", status: "1", position: "12", children: [] }, { root: "15", id: "19", name: "Giallo/Arancio", status: "1", position: "13", children: [] }, { root: "15", id: "20", name: "Rosso", status: "1", position: "14", children: [] }] }, { root: "0", id: "25", name: "Persone", status: "1", position: "24", children: [{ root: "25", id: "26", name: "Fabrizio", status: "1", position: "2", children: [{ root: "26", id: "27", name: "Uomo", status: "1", position: "21", children: [] }] }, { root: "25", id: "28", name: "Ivan", status: "1", position: "1", children: [] }] }, { root: "0", id: "29", name: "Category", status: "1", position: "25", children: [] }],
flat = tree.reduce(flatTree(), []);
console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }
给定这棵树,是否有一种简单的方法可以将其转换为具有以下条件的平面数组?
- JS ES5,jQuery 也用过
- 尊重呈现顺序
- 添加一个"level" 属性表示缩进级别,从0 开始
[
{
"root": "0",
"id": "1",
"name": "Frutta",
"status": "1",
"position": "1",
"children": [
{
"root": "1",
"id": "4",
"name": "Agrumi",
"status": "1",
"position": "3",
"children": []
},
{
"root": "1",
"id": "5",
"name": "Pere",
"status": "1",
"position": "4",
"children": []
}
]
},
{
"root": "0",
"id": "2",
"name": "Ortaggi",
"status": "1",
"position": "1",
"children": [
{
"root": "2",
"id": "7",
"name": "Da foglia",
"status": "1",
"position": "6",
"children": [
{
"root": "7",
"id": "9",
"name": "Insalate",
"status": "1",
"position": "1",
"children": []
}
]
},
{
"root": "2",
"id": "8",
"name": "Da fiore",
"status": "1",
"position": "7",
"children": []
},
{
"root": "2",
"id": "21",
"name": "Da frutto",
"status": "1",
"position": "16",
"children": []
},
{
"root": "2",
"id": "22",
"name": "Da radici",
"status": "1",
"position": "17",
"children": []
},
{
"root": "2",
"id": "23",
"name": "Da fusto",
"status": "1",
"position": "8",
"children": []
},
{
"root": "2",
"id": "24",
"name": "Da bulbi",
"status": "1",
"position": "18",
"children": []
}
]
},
{
"root": "0",
"id": "15",
"name": "Colori",
"status": "1",
"position": "14",
"children": [
{
"root": "15",
"id": "3",
"name": "Banane",
"status": "1",
"position": "2",
"children": [
{
"root": "3",
"id": "6",
"name": "Mele",
"status": "1",
"position": "5",
"children": []
}
]
},
{
"root": "15",
"id": "16",
"name": "Blu/Viola",
"status": "1",
"position": "10",
"children": []
},
{
"root": "15",
"id": "17",
"name": "Verde",
"status": "1",
"position": "11",
"children": []
},
{
"root": "15",
"id": "18",
"name": "Bianco",
"status": "1",
"position": "12",
"children": []
},
{
"root": "15",
"id": "19",
"name": "Giallo/Arancio",
"status": "1",
"position": "13",
"children": []
},
{
"root": "15",
"id": "20",
"name": "Rosso",
"status": "1",
"position": "14",
"children": []
}
]
},
{
"root": "0",
"id": "25",
"name": "Persone",
"status": "1",
"position": "24",
"children": [
{
"root": "25",
"id": "26",
"name": "Fabrizio",
"status": "1",
"position": "2",
"children": [
{
"root": "26",
"id": "27",
"name": "Uomo",
"status": "1",
"position": "21",
"children": []
}
]
},
{
"root": "25",
"id": "28",
"name": "Ivan",
"status": "1",
"position": "1",
"children": []
}
]
},
{
"root": "0",
"id": "29",
"name": "Category",
"status": "1",
"position": "25",
"children": []
}
]
预期的结果应该是这样的:
[
{
"root": "0",
"id": "1",
"name": "Frutta",
"status": "1",
"position": "1"
"level": 0
},
{
"root": "1",
"id": "4",
"name": "Agrumi",
"status": "1",
"position": "3",
"level": 1
},
{
"root": "1",
"id": "5",
"name": "Pere",
"status": "1",
"position": "4",
"level": 1
},
{
"root": "0",
"id": "2",
"name": "Ortaggi",
"status": "1",
"position": "1",
"level": 0
},
{
"root": "2",
"id": "7",
"name": "Da foglia",
"status": "1",
"position": "6",
"level": 1
},
{
"root": "7",
"id": "9",
"name": "Insalate",
"status": "1",
"position": "1",
"level": 2
},
...
我找到了这个函数,但有一些缺点:
var flattenTree = function(treeObj, idAttr, parentAttr, childrenAttr, levelAttr) {
if (!idAttr) idAttr = 'id';
if (!parentAttr) parentAttr = 'root';
if (!childrenAttr) childrenAttr = 'children';
if (!levelAttr) levelAttr = 'level';
function flattenChild(childObj, parentId, level) {
var array = [];
var childCopy = $.extend({}, childObj);
childCopy[levelAttr] = level;
childCopy[parentAttr] = parentId || "0";
delete childCopy[childrenAttr];
array.push(childCopy);
array = array.concat(processChildren(childObj, level));
return array;
};
function processChildren(obj, level) {
if (!level) level = 0;
var array = [];
obj[childrenAttr].forEach(function(childObj) {
array = array.concat(flattenChild(childObj, obj[idAttr], level+1));
});
return array;
};
var result = processChildren(treeObj);
return result;
};
- 我应该首先构建另一个以 "children" 开头的数组作为根
[
"children": <my original array here>
]
- 级别从 1 开始,而不是 0(我尝试输入
level = -1
但没有成功)
这是一个有效的 fiddle:https://jsfiddle.net/yLke452z/
谢谢
您可以对 Array#flatMap
采取递归方法并存储下一次调用的级别。
const
flatTree = (level = 0) => ({ children = [], ...object }) => [
{ ...object, level }, ...children.flatMap(flatTree(level + 1))
];
var tree = [{ root: "0", id: "1", name: "Frutta", status: "1", position: "1", children: [{ root: "1", id: "4", name: "Agrumi", status: "1", position: "3", children: [] }, { root: "1", id: "5", name: "Pere", status: "1", position: "4", children: [] }] }, { root: "0", id: "2", name: "Ortaggi", status: "1", position: "1", children: [{ root: "2", id: "7", name: "Da foglia", status: "1", position: "6", children: [{ root: "7", id: "9", name: "Insalate", status: "1", position: "1", children: [] }] }, { root: "2", id: "8", name: "Da fiore", status: "1", position: "7", children: [] }, { root: "2", id: "21", name: "Da frutto", status: "1", position: "16", children: [] }, { root: "2", id: "22", name: "Da radici", status: "1", position: "17", children: [] }, { root: "2", id: "23", name: "Da fusto", status: "1", position: "8", children: [] }, { root: "2", id: "24", name: "Da bulbi", status: "1", position: "18", children: [] }] }, { root: "0", id: "15", name: "Colori", status: "1", position: "14", children: [{ root: "15", id: "3", name: "Banane", status: "1", position: "2", children: [{ root: "3", id: "6", name: "Mele", status: "1", position: "5", children: [] }] }, { root: "15", id: "16", name: "Blu/Viola", status: "1", position: "10", children: [] }, { root: "15", id: "17", name: "Verde", status: "1", position: "11", children: [] }, { root: "15", id: "18", name: "Bianco", status: "1", position: "12", children: [] }, { root: "15", id: "19", name: "Giallo/Arancio", status: "1", position: "13", children: [] }, { root: "15", id: "20", name: "Rosso", status: "1", position: "14", children: [] }] }, { root: "0", id: "25", name: "Persone", status: "1", position: "24", children: [{ root: "25", id: "26", name: "Fabrizio", status: "1", position: "2", children: [{ root: "26", id: "27", name: "Uomo", status: "1", position: "21", children: [] }] }, { root: "25", id: "28", name: "Ivan", status: "1", position: "1", children: [] }] }, { root: "0", id: "29", name: "Category", status: "1", position: "25", children: [] }],
flat = tree.flatMap(flatTree());
console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES5 与 Array#reduce
.
function flatTree(level) {
return function(result, object) {
var children = object.children || [],
item = Object.keys(object).reduce(function (o, k) {
if (k !== 'children') o[k] = object[k];
return o;
}, {});
level = level || 0;
item.level = level;
return result.concat(item, children.reduce(flatTree(level + 1), []));
};
}
var tree = [{ root: "0", id: "1", name: "Frutta", status: "1", position: "1", children: [{ root: "1", id: "4", name: "Agrumi", status: "1", position: "3", children: [] }, { root: "1", id: "5", name: "Pere", status: "1", position: "4", children: [] }] }, { root: "0", id: "2", name: "Ortaggi", status: "1", position: "1", children: [{ root: "2", id: "7", name: "Da foglia", status: "1", position: "6", children: [{ root: "7", id: "9", name: "Insalate", status: "1", position: "1", children: [] }] }, { root: "2", id: "8", name: "Da fiore", status: "1", position: "7", children: [] }, { root: "2", id: "21", name: "Da frutto", status: "1", position: "16", children: [] }, { root: "2", id: "22", name: "Da radici", status: "1", position: "17", children: [] }, { root: "2", id: "23", name: "Da fusto", status: "1", position: "8", children: [] }, { root: "2", id: "24", name: "Da bulbi", status: "1", position: "18", children: [] }] }, { root: "0", id: "15", name: "Colori", status: "1", position: "14", children: [{ root: "15", id: "3", name: "Banane", status: "1", position: "2", children: [{ root: "3", id: "6", name: "Mele", status: "1", position: "5", children: [] }] }, { root: "15", id: "16", name: "Blu/Viola", status: "1", position: "10", children: [] }, { root: "15", id: "17", name: "Verde", status: "1", position: "11", children: [] }, { root: "15", id: "18", name: "Bianco", status: "1", position: "12", children: [] }, { root: "15", id: "19", name: "Giallo/Arancio", status: "1", position: "13", children: [] }, { root: "15", id: "20", name: "Rosso", status: "1", position: "14", children: [] }] }, { root: "0", id: "25", name: "Persone", status: "1", position: "24", children: [{ root: "25", id: "26", name: "Fabrizio", status: "1", position: "2", children: [{ root: "26", id: "27", name: "Uomo", status: "1", position: "21", children: [] }] }, { root: "25", id: "28", name: "Ivan", status: "1", position: "1", children: [] }] }, { root: "0", id: "29", name: "Category", status: "1", position: "25", children: [] }],
flat = tree.reduce(flatTree(), []);
console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }