
关于多维数组取数据的循环浅谈
😂 这篇文章最后更新于1025天前,您需要注意相关的内容是否还可用。
这个问题的起源,来自我在Coding的冒泡中,看到某位泡友的根据返回地区id查询对应的名称;
看了写法以后,不禁想起我这些年做的类似栗子。
突然想到了一些可取之处,在这里总结一些开发经验。
首先,我先预设一个虚构的多维数组结构
var data = [ { "id": 1, "name": "A", "list": [ { "id": 1, "name": "AA", "list": [ { "id": 1, "name": "AAA" }, { "id": 2, "name": "AAB" } ] }, { "id": 2, "name": "AB", "list": [ { "id": 1, "name": "ABA" }, { "id": 2, "name": "ABB" } ] } ] }, { "id": 2, "name": "B", "list": [ { "id": 1, "name": "BA", "list": [ { "id": 1, "name": "BAA" }, { "id": 2, "name": "BAB" } ] }, { "id": 2, "name": "BB", "list": [ { "id": 1, "name": "BBA" }, { "id": 2, "name": "BBB" } ] } ] } ]
考虑到篇幅的问题,做了2*2*2的多维数组;
现已知id(1,1,2) 求对应的Name组成值;
实现方法1,最原始,最消耗资源的写法:
var ids = [1, 1, 2] var names = [] for (var i = 0; i < data.length; i++) { if (data[i].id == ids[0]) { names.push(data[i].name) for (var j = 0; j < data[i].list.length; j++) { if (data[i].list[j].id == ids[1]) { names.push(data[i].list[j].name) for (var k = 0; k < data[i].list[j].list.length; k++) { if (data[i].list[j].list[k].id == ids[1]) { names.push(data[i].list[j].list[k].name) } } } } } } console.log(names.join(",")) // A,AA,AAB
这种写法,算是最粗暴的写法了,直接嵌套三个for循环,然后得到数据;
在我们初学程序代码的时候,这种写法估计写过不少,后来成熟一些后,对其进行改进
实现方法2,简单优化的方法1:
// 简单优化 var ids = [1, 1, 2] var names = [] for (var i = 0, n = data.length; i < n; i++) { if (data[i].id == ids[0]) { names.push(data[i].name) for (var j = 0, z = data[i].list.length; j < z; j++) { if (data[i].list[j].id == ids[1]) { names.push(data[i].list[j].name) for (var k = 0, x = data[i].list[j].list.length; k < x; k++) { if (data[i].list[j].list[k].id == ids[1]) { names.push(data[i].list[j].list[k].name) break } } break } } break } } console.log(names.join(",")) // A,AA,AAB
现在单独声明长度,添加了break阻止不必要继续循环,算是有所成长,但依旧很粗暴
实现方法3,ES3环境,相对靠谱的写法
// ES3环境下,我目前最好的优化 var ids = [1, 1, 2] var names = [], list1 = [], list2 = [] for (var i = 0, n = data.length; i < n; i++) { if (data[i].id == ids[0]) { names.push(data[i].name) list1 = data[i].list break } } for (var i = 0, n = list1.length; i < n; i++) { if (list1[i].id == ids[1]) { names.push(list1[i].name) list2 = list1[i].list break } } for (var i = 0, n = list2.length; i < n; i++) { if (list2[i].id == ids[2]) { names.push(list2[i].name) break } } console.log(names.join(",")) // A,AA,AAB
虽然还是三个for循环,但其中改进的地方,就不是一点点了。
针对这三种写法,我们做一个计算题,大概就知道其中的优势了;
方法1,循环次数为 2*2*2;属于一定会执行这么多次的写法;
方法2,循环次数最小为1+1+1,最大为2*2*2,这个取决于id的次数计算,只是让你感觉会比方法1的压力小很多;
方法3,循环次数最小为1+1+1,最大为2+2+2,同样是取决于id的次数计算,加法远比乘法轻松很多;假设,我们这栗子是10*10*10的多维数组,30与1000之间差距,是否就很明显了?
当然,我写这些东西,并不是要否定for嵌套循环的左右,只是大家需要考虑到善用循环嵌套,才能写出最漂亮的代码。
嗯,放一个ES6版的写法
// ES6,就简单多了 const ids = [1, 1, 2]; const obj_1 = data.find(i => i.id == ids[0]); const obj_2 = obj_1.list.find(i => i.id == ids[1]); const obj_3 = obj_2.list.find(i => i.id == ids[2]); console.log([obj_1.name, obj_2.name, obj_3.name].join(",")); // A,AA,AAB
这个算是比较少和漂亮的代码,如果数组数据更为庞大,有时候需要更好的递归写法,这个就是我暂时没法演示的内容了。
关于array.find,需要了解的朋友,可以前往MDN查询