export class TreeHelper {
/**
*
* @param items 扁平数据数组
* @param idMapper 数组元素的id映射
* @param parentIdMapper 数组元素的父节点id映射
* @param objectMapper 数组元素映射为另一种类型的对象,默认为undefined,即使用源对象类型
* @returns 树形数据数组
*/
public static arrayToTree<S, T>(
items: any[],
idMapper: (item: S) => string | number,
parentIdMapper: (item: S) => string | number,
objectMapper: (item: S) => T = undefined,
childrenProperty: string = 'children'
) {
// 已数据id为属性的map,用于暂存数据和快速存取父元素
const map = {};
// 使用数组的reduce过程,逐个循环,收敛结果到第一层数组
const tree = items.reduce((prev: T[], curr: S) => {
// 生成新的元素
const tmp = objectMapper ? objectMapper(curr) : curr;
const newItem: any = { ...tmp } as T;
// 对树形元素的子树数组赋值,
// 由于是一次循环,有可能在前面已经找到子节点,从而先创建了父节点,
// 所以如果在map中找到当前id为属性的节点,需要将子树合并过来
const id = idMapper(curr);
newItem[childrenProperty] = map.hasOwnProperty(id) ? map[id][childrenProperty] : [];
// 将当前节点放回map中
map[id] = newItem;
// 寻找找父节点
let parentId = parentIdMapper(curr);
if (!parentId) {
// 如果不存在父节点,则将当前节点放入第一层
prev.push(newItem);
} else {
// 如果存在父节点,则将当前节点放到父节点的子树中
if (!map.hasOwnProperty(parentId)) {
// 如果map中不存在父节点,则先创建一个临时的父节点
map[parentId] = {};
map[parentId][childrenProperty] = [];
}
map[parentId][childrenProperty].push(newItem);
}
// 返回第一层数组,继续归并下一个元素
return prev;
}, []);
return tree;
}
}
09-01
509
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
04-07
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交