如何优化多层for循环

6,804 阅读3分钟

在开发的过程中我们会处理大量的数据,在日常开发中我们喜欢把数据存放在对象里面,不管是参数,还是后台接口返回出来的数据绝大多数都是以json的形式存储。例如var obj=[{},{},{}],如果2个或者多个这样的数据交叉获取数据,势必就会用到循环。如果嵌套很多的for循环,数据量又大的时候,你的页面就会出现白屏,甚至是浏览器的崩溃。那么如何优化多层for循环呢?请看下面的例子。

为了能够直观的验证代码请在本地安装nodejs,之后只需要建立一个js文件即可。

例子:在js文件里面
const school={
  "students": [
    {
      "id": "001",
      "glassname":"一年级"
    },{
      "id": "002",
      "glassname":"二年级"
    },
  ]
  const students={
    "glass":[
       { 
	   "student":[
	      {
			"id":"001"
		  },{
			"id":"002",
			"username":"李四",
			"age":11
		  }
	   ]
       },{
	    "student":[
	      {
		   "id":"001",
		   "username":"王五",
		   "age":12
		  },{
		   "id":"002"
		  }
	   ]
	
    }
 ]    }

需求:列表有3列展示内容来源于school.students,列表的第三行和第四行展示展示students.glass里面匹配到的数据,最后的数据格式应该是:

const school={ "students": [ { "id": "001", "glassname":"一年级", "username":"王五", "age":12 },{ "id": "002", "glassname":"二年级", "username":"李四", "age":12 } ] } 或许有人会说我组装上就好了,干嘛要写个程序做,那我想问你,此时这个例子比较简单,数据量很小你可以组装,如果数据量达到10万条呢?如果对象结构复杂到包含的属性有100个呢,你还能手动组装出来吗? 此时不得不找程序,看看最土的办法:

例子:

for(var i=0;i<school.students.length;i++){
	var schoolId=school.students[i].id;
    for(var j=0;j<students.glass.length;j++){
	   var student=students.glass[j].student;
	   for(var z=0;z<student.length;z++){
		   var studentId=student[z].id
          if(schoolId==studentId && student[z].username){
			school.students[i].username=student[z].username;
			school.students[i].age=student[z].age;
			console.log(student[z].username,student[z].age)
		  }
	   }
	}
}

看着上面的代码有没有想死的心,虽然你觉得自己逻辑很清楚,但是写着写着你就凌乱了。上线2个月以后连你自己都不知道他在干嘛,真的想死呢,并且如果数据量一旦上千他的速度都会慢到一分钟,对客户来说,你的页面一分钟后才能展示出来,他能忍受吗? 所以说以上嵌套循环有2个问题,1.代码不易维护,2.性能消耗太大。 那如何要你的代码更加清晰易懂呢?

const getList= function (school, students) {
	if (!school || !students) {
	  return;
	}
	const MAP = {};
	// 循环将有效的时间和数值都存到一个对象里面
	const studata =school.students;
	const glass =students.glass;
  
	glass.forEach((item) => {
	  if (!item.student.length) {
		return;
	  } 
	  item.student.forEach(stuItem => {
		if(!stuItem.username||!stuItem.age){
			 return;//一定是return,而不是break,因为他是forEach
		}
		MAP[stuItem.id] = {
			username: stuItem.username,
			age: stuItem.age
		  }

	  });
	  
	})
	//直接从对象里面获取象要的值即可
	studata.forEach((limitPkg) => {
	  const detail = MAP[limitPkg.id];
	  if (detail) {
		limitPkg.username = detail.username;
		limitPkg.age = detail.age;
	  }
	})
	return studata
  }
  var result=getList(school, students)
  console.log(JSON.stringify(result))

有没有觉得上面的代码就清晰很多,他的原理是将你想要存在一个对象里面,把原来需要匹配的条件作为key值。

我想在开发中你需要理解的是解决问题的思路,而不是代码。所以还请读者多多揣摩代码里面所做的一些技巧性的处理。