Эта функция выполняет задание, плюс добавляет индикатор уровня к каждому объекту. Непосредственными детьми treeObj будет уровень 1, их дети будут уровнем 2 и т. Д. Обновлены свойства parent
.
function flatten(treeObj, idAttr, parentAttr, childrenAttr, levelAttr) {
if (!idAttr) idAttr = 'id';
if (!parentAttr) parentAttr = 'parent';
if (!childrenAttr) childrenAttr = 'children';
if (!levelAttr) levelAttr = 'level';
function flattenChild(childObj, parentId, level) {
var array = [];
var childCopy = angular.extend({}, childObj);
childCopy[levelAttr] = level;
childCopy[parentAttr] = parentId;
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;
};
Это решение имеет преимущество angular.extend()
функции угловой, чтобы выполнить копию дочернего объекта. Проведение этого с использованием эквивалентного метода другой библиотеки или собственной функции должно быть тривиальным изменением.
Выходной сигнал дается для приведенного выше примера будет:
[{
"id": 1,
"title": "home",
"parent": null,
"level": 1
}, {
"id": 2,
"title": "about",
"parent": null,
"level": 1
}, {
"id": 3,
"title": "team",
"parent": 2,
"level": 2
}, {
"id": 4,
"title": "company",
"parent": 2,
"level": 2
}]
Также стоит отметить, что эта функция не гарантирует массив будет упорядочен по id
; он будет основываться на порядке, в котором отдельные объекты были обнаружены во время операции.
Fiddle!
Я нашел много вопросов о том, как создать дерево из массива, но ни один преобразовывая назад в другом направлении, поэтому я разместил решение I придумал. –