欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS从“深度优先”和“广度优先”遍历获取数据中某一属性值的集合

程序员文章站 2022-05-20 19:07:51
...

JS实现深度优先遍历和广度优先遍历

1、要求

  • 获取以下数据结构中所有name属性值的集合。
  • 数据的结构如下:
const myData = [
  {
      name: 'a',
      children: [
          { name: 'b', children: [{ name: 'e' }] },
          { name: 'c', children: [{ name: 'f' }] },
          { name: 'd', children: [{ name: 'g' }] },
      ]
  },
  {
      name: 'a2',
      children: [
          { name: 'b2', children: [{ name: 'e2' }] },
          { name: 'c2', children: [{ name: 'f2' }] },
          { name: 'd2', children: [{ name: 'g2' }] },
      ],
  }
]

2、实现

2.1、深度优先遍历

  • 思路:先深拷贝数据>>>内部创建一个deep函数,通过for…in…来判断所有键(或项)的值是否为数组或对象>>>如果值为数组或对象,则将该值作为遍历的数组或对象递归调用。如果不是,则检查该键(项)是否为name,是则放入到result数组中。
  • 程序如下:
function deepTraversal(data) {
	const temp = JSON.parse(JSON.stringify(data));
	const result = [];
	function deep(list) {
		//只有list不为null时才执行
		if (list) {
			for (let key in list) {
				//如果list[key]的值是对象或数组,则继续深度遍历
				//数组、对象或null的typeof结果都为object。此处也可以用constructor来判断
				if (typeof list[key] === "object") {
					deep(list[key]);				
				} else {
					//如果不是数组也不是对象,则分析key是否为name
					if (key === "name") {
						result.push(list[key])
					}
				}
			}
		} return;
	}
	deep(temp);
	return result
}
console.log(deepTraversal(myData));
  • 输出结果:
    ["a", "b", "e", "c", "f", "d", "g", "a2", "b2", "e2", "c2", "f2", "d2", "g2"]

2.2、广度优先遍历

  • 思路:先深拷贝数据>>>>创建trans空数组(用来保存每次得到的下一级节点),wide函数(用来分析哪个子节点的值是否为数组或函数)>>>只要trans不为空,则会继续分析下一级节点
  • 程序如下:
function wideTraversal(data) {
	const temp = JSON.parse(JSON.stringify(data));
	const result = [];
	const trans = [];	//保存过渡用到的子节点
	function wide(list) {
		if (list) {
			//每递归一次(表示遍历了某个子节点),遍历完则移除该节点
			trans.shift();
			for (let key in list) {
				//分析值是否为对象或数组
				if (typeof list[key] === "object") {
					trans.push(list[key]);
				} else {
					if (key === "name") {
						result.push(list[key])	
					}
				}
			}
		}
		// 如果过渡数组中有项,则会遍历该数组,并递归调用wide
		if (trans) {
			trans.forEach(child => {
				wide(child);
			})
		}
	}
	wide(temp);
	return result
}
console.log(wideTraversal(myData));
  • 运行结果:
    ["a", "a2", "b", "c", "d", "b2", "c2", "d2", "e", "f", "g", "e2", "f2", "g2"]

3、 总结

  • 网上有很多更好用的方法,也是从深度和广度两个方面遍历数据或节点树。这两个方法,我是通过思考和实践写出来了。
  • 优点:相对比较容易理解。缺点:代码量确实比网上的方法要大一半。
  • 自学前端半年,萌新入门,欢迎各位技术大拿提出意见和指教。