开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情
前言:
成功没有捷径但成长有路径
css必备场景。专注积累,每天记录一个知识点,老概念新理解,重点记录一下
每天梳理一个场景,知识点查漏补缺,充实满足。
正文
背景
最近复习,看到一个比较常用的算法,数组扁平的数据结构,需要把他转成树。这种需求在开发中经常使用到,应用场景比如说省市区的,树状图表之类的处理,不使用异步加载的情况,如果后端没有给树结构,而是一个扁平化的数据,我们需要把扁平数组转成级联的形式。不考虑性能问题,我们梳理几个最常用的方法。
扁平的数据是这样的
let arr = [
{
dictCode: '370000',
dictName: '山东省',
dictParentCode: 'CN',
dictType: 1 },
{
dictCode: '370100',
dictName: '济南市',
dictParentCode: '370000',
dictType: 1,
},
{
dictCode: '370101 ',
dictName: '市辖区',
dictParentCode: '370100',
dictType: 1,
},
{
dictCode: '370200',
dictName: '青岛市',
dictParentCode: '370000',
dictType: 1,
}
];
要输出的结果
let arrTree = [
{
dictCode: '370000',
dictName: '山东省',
dictParentCode: 'CN',
dictType: 1,
children: [
{
dictCode: '370100',
dictName: '济南市',
dictParentCode: '370000',
dictType: 1,
children: [
{
dictCode: '370101 ',
dictName: '市辖区',
dictParentCode: '370100',
dictType: 1,
}
],
},
{
dictCode: '370200',
dictName: '青岛市',
dictParentCode: '370000',
dictType: 1,
},
],
},
];
方法
list to tree
扁平数组=>树结构数据
递归
递归主要思路,无脑执行,我们需要一个查子元素的方法,从rooId开始,不考虑性能一层一层遍历,获取所有的children,再递归调用该方法获取子children,直到查到所有。弊端就是性能问题
因为还要考虑到接口返回名称不一样,要做到方法通用, idKey, parentKey可以通过传值方式
/**
*@param {arr: array 原数组数组, id:根节点id, idKey:节点名称,parentKey:父节点名称
*@return {children:array子数组}
*/
function listToTree(arr, rootId, idKey = 'id', parentKey = 'pid') {
const res = [];
for (const item of arr) {
if (item[parentKey] === rootId) {
res.push({
...item,
children: getChildren(arr, item[idKey], idKey, parentKey),
});
}
}
return res;
}
// 执行
listToTree(arr,'CN','dictCode','dictParentCode')
循环Map
利用对象的弱引用,相比递归性能上要好一些,创建一个map数据结构的字典,遍历找到数据修改它的children。下面这种写法,这只是一种思路, map的形式有很多种写法。
function listToTree(list = [], idKey, parentKey, rootId = 'CN') {
const result = [];
//创建一个map数据字典
const dictionary = list.reduce((pre, cur) => {
pre[cur[idKey]] = { ...cur, children: [] };
return pre;
}, {});
list.forEach((item) => {
//在字典中查找对应的数据
const parent = dictionary[item[parentKey]];
if (parent) {
//修改它的children
parent.children.push(dictionary[item[idKey]]);
} else {
//如果没找到就指定一个根节点
result.push(dictionary[item[idKey]]);
}
});
return result;
}
// 执行
listToTree(arr, 'dictCode', 'dictParentCode', 'CN')