数组转树
代码语言:javascript
复制var tree1 = [{
"p_id": 0,
"id": 33,
"name": "港澳",
},
{
"p_id": 33,
"id": 3477,
"name": "香港特别行政区",
},
{
"p_id": 33,
"id": 3478,
"name": "澳门特别行政区",
},
{
"p_id": 3477,
"id": 3502,
"name": "九龙城区"
},
{
"p_id": 0,
"id": 6,
"name": "辽宁省",
},
{
"p_id": 6,
"id": 645,
"name": "抚顺市"
},
]
递归1
代码语言:javascript
复制/**
* 性能最差,全部递归。
* 思想:把所有数据都当成子层,传入一个pid,获取所有id等于pid的数据,
* 且当id等于pid时,先获取当前项的所有children,获取到当前项的所有children后,
* 再将该项连同获取到的children存到res里,当遍历完了后,就可以获取所有指定pid的树型数据,最后返回res
*/
function toTree(arr, pid) {
// 循环,获取该id的children
function loop(pid) {
// 保存得到的数据
var res = [];
// 遍历原数组
for (var i = 0; i < arr.length; i ) {
var item = arr[i]
if (item.p_id === pid) {
// 如果遍历到当前item的p_id等于目标pid,在将该item插入到res前,
// 先遍历该item的id,找到原数组arr里面该item的所有children后,再将该item连同找到的children一起插入到res
item.children = loop(item.id)
// 如果当前item的p_id等于目标pid,则将这个item插入res
res.push(item)
}
}
return res
}
return loop(pid)
}
console.log(toTree(tree, 0));
递归2
代码语言:javascript
复制/**
* 第一次:传入tree以及父id:0,即找出tree里面所有父id是0的树型结构数据,
* 进入for循环,第一次找到了港澳,港澳的id是33,
* 再次重新遍历,找出tree里面所有p_id等于33的数据,
* 遍历数据,首先找到香港的p_id是等于33,此时,不要直接将香港给港澳的children,
* 而是先找香港的所有子,香港的id是3477,因此遍历所有数据,找到了九龙的p_id是3477,
* 然后再找九龙的所有子,九龙的id是3502,遍历所有数据,找不到p_id是3502的数据,
* 因此代表九龙下面没有子了,回到九龙的p_id,即香港,将九龙放到香港的children里,
* 然后再次遍历继续找香港下面的子,但是找不到香港的子了,因此香港的数据找完了,将香港插入港澳的children,
* 然后再次遍历,找到澳门的p_id等于33,此时,也是不要直接将澳门给港澳的children,
* 而是先找到澳门的所有子,澳门的id是3478,因此遍历所有数据,找不到p_id是3478的数据,
* 因此代表澳门下面没有子,将澳门插入港澳的children,
* 最后继续遍历,找不到p_id是33的数据了,就把香港和澳门插入到港澳下面的children
* 开始进入第二次遍历,找到澳门,其实澳门遍历过了,优化的时候要将遍历过的数据删掉
* 优化后,第二次找到的应该是辽宁,辽宁的id是6,遍历当前数据(已经遍历过的已经删了),
* 找出里面所有p_id等于6的数据,找到抚顺市的p_id是6,此时,不要直接将抚顺给辽宁的children,
* 而是先找抚顺的所有子,抚顺的id是645,因此遍历当前数据,找不到id是645的数据,即代表
* 抚顺没有子,继续找出p_id等于6的数据,遍历后没有找到数据,代表辽宁省数据找完了,
* 将抚顺插入到辽宁省,
* 开始进入第三次遍历,但是这时候已经遍历完了(因为遍历过的都被删了)
* 最后返回修改后的数组
*/
function formatTree(arr) {
// 因为数组里面的是对象(引用),因此为了不改变原数组最好先深拷贝一下
var _arr = JSON.parse(JSON.stringify(arr))
var _parent = _arr.filter(item => item.p_id == 0);
var _children = _arr.filter(item => item.p_id != 0);
var all = arr.filter(item => true)
toTree(_parent, _children)
function toTree(parent, children) {
parent.map(p => {
children.map((c, index) => {
if (p.id == c.p_id) {
// 如果当前父id等于子pid,则先递归找到子的所有子,然后再插入到父里面
_children = JSON.parse(JSON.stringify(children))
// 每次遍历一个就删掉一个,以免重复遍历
_children.splice(index, 1)
toTree([c], _children)
if (p.children) {
p.children.push(c)
} else {
p.children = [c]
}
}
})
})
}
return _parent
}
console.log(formatTree(tree1));
非递归
代码语言:javascript
复制function formatTree1(arr) {
// 因为数组里面的是对象(引用),因此为了不改变原数组最好先深拷贝一下
var _arr = JSON.parse(JSON.stringify(arr))
// 遍历所有数据
var newarr = _arr.filter(p => {
// 获取当前父数据的所有children
var temp = _arr.filter(c => p.id == c.p_id)
// var temp = arr.filter(c => p.id == c.p_id) //错误写法,这样的话并不会将
// 如果获取到了有children,则将该children给父
temp.length && (p.children = temp)
// 最后返回这个p
return p.p_id == 0
})
return newarr
}
console.log(formatTree1(tree1));
/**
* 思想:将每一项都当作父,找他的子
* 遍历第一个时,遍历所有数据,将属于他的children找出来,然后给添加到自己上面
* 然后第二个遍历继续,遍历所有数据,将属于他的children找出来,然后给添加到自己上面
* 直到遍历到最后一个(即遍历完所有数据)
* 举例:tree1里面map先遍历第一个,第一个是港澳,港澳的p_id是0,遍历全部数据,找不到id是0的数据,
* 继续遍历第二个,第二个是香港,香港的p_id是33,遍历全部数据,只找到港澳的id是33,将香港插入到港澳,
* 继续遍历第三个,第三个是澳门,澳门的p_id是33,遍历全部数据,只找到港澳的id是33,将澳门插入到港澳,
* 继续遍历第四个,第四个是九龙,九龙的p_id是3477,遍历全部数据,只找到香港的id是3477,将九龙插入到香港,
* 注意,关键:这里遍历修改的都是原数组,一开始将香港的引用给了港澳,后面又将九龙给了香港,因此,这时的港澳里
* 面除了一开始的香港和澳门,还有多一个九龙在香港里面
* 后面的就跟上面的类似,不再继续写了
*/