算法 ——平扁数组转树(1)

数据源:

let arr = [
	{ id: 4, pid: 2, name: 'd' },
	{ id: 1, pid: 0, name: 'a' },
	{ id: 3, pid: 1, name: 'c' },
	{ id: 5, pid: 0, name: 'e' },
	{ id: 7, pid: 6, name: 'f' },
	{ id: 6, pid: 5, name: 'f' },
	{ id: 78, pid: 1, name: 'h' },
	{ id: 8, pid: 1, name: 'g' },
	{ id: 2, pid: 0, name: 'b' },
]

第一种方案核心思想父亲找孩子+递归

实现思路:

1、将数组分成两类,父节点和子节点,parent,originChildren。

2、遍历父节点找孩子,如果找到孩子就把孩子放到父节点children属性的数组中。

3、通过递归将让子节点去找它的下级子节点。

疑点:children和originChildren是引用类型,引用类型的特点就是指向同一个引用地址的变量,无论是哪一个修改了数据源,他们获取到的数据都是保持一致;

代码如下:

function toTree(arr, pid) {
	const parent = arr.filter(p => p.pid === pid),
		originChildren = arr.filter(c => c.pid !== pid);
	for (let p of parent) {
		findChildren(p, originChildren)
	}
	function findChildren(p, originChildren) {
		let _p = undefined;
		//遍历查找当前父节点的所有孩子
		for (let index = 0; index < originChildren.length; index++) {
			if (originChildren[index].pid === p.id) {
				// 把找到的子节点从子节点的数据源中剔除,
				// 目的是减少子节点数据源的个数,提高命中率。
				_p = originChildren.splice(index, 1)[0];
                //由于删除了当前下标对应的元素,导致数组后面的元素往前移动,
                //所以要把当前下标往前移一位。
				index = index - 1; //
				if (p.children) {
					p.children.push(_p)
				} else {
					p.children = [_p]
				}
				findChildren(_p, originChildren)
			}
		}
	}
	return parent
}

调用:console.log(toTree(arr));

第二种方案的核心思想:孩子找父亲+map; 

实现思路:

1、遍历数组,以元素的id为键,元素为值 ;添加到map中;

2、遍历数组,如果元素的pid等于parentId(根元素),直接添加到res数组中

3、否则提高map.get(item.pid)获取父节点(孩子找父亲)

实现代码:

function toTree(data, parentId = 0) {
	let map = new Map(),
		res = [];
	data.forEach(item => map.set(item.id, item));
	data.forEach(item => {
		let { pid } = item,
		parent = undefined;
		if (pid === parentId) {
			res.push(item)
		} else {
			parent = map.get(pid);
			parent.children ? parent.children.push(item) : parent.children = [item]
		}
	})
	return res
}
console.log(toTree(arr, 0));

map可以换成object或者数组:通过属性后绑定,代码如下:

function toTree(data, parentId = 0) {
	let map ={},
		res = [];
	data.forEach(item => map[item.id]=item);
	console.log(map);
	data.forEach(item => {
		let { pid } = item,
		parent = undefined;
		if (pid === parentId) {
			res.push(item)
		} else {
			parent = map[pid];
			parent.children ? parent.children.push(item) : parent.children = [item]
		}
	})
	return res
}
			

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值