js处理大数据数组循环的一些性能优化

338 阅读4分钟
前言

观察者模式,是一种设计模式。这些设计模式就是一些思路。当然,关于排序,有快速排序法,关于查找有二分查找法等等,这些都为我们提供了一些思路。那么对于避免不了的大数据循环,分类,查找,有什么更加提高性能,或者说是降低内存消耗的方法吗?

案例

假设后端返回数据如下:
[JavaScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
{
"code": 0,
"message": "",
"data": {
"list": [{
"city_level": "CITY_LEVEL_NONE",
"parent_id": 0,
"name": "中国未知",
"id": 156
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 0,
"name": "台湾省",
"id": 710000
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "台湾省未知",
"id": 719900
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "高雄市",
"id": 710200
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "花莲县",
"id": 712200
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "嘉义市",
"id": 710700
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "南投县",
"id": 711500
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "澎湖县",
"id": 712300
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "屏东县",
"id": 712000
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "台北市",
"id": 710100
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "台东县",
"id": 712100
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "台南市",
"id": 710500
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "台中市",
"id": 710400
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "桃园市",
"id": 711100
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "新竹市",
"id": 710600
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "宜兰县",
"id": 710900
}, {
"city_level": "CITY_LEVEL_NONE",
"parent_id": 710000,
"name": "云林县",
"id": 711700
}, ...........//此处省略上千条
]
}
}
上面的数据假设是全世界5000多个城市的数据,城市可能分为几个级别,省、市、区等等。
现在要把这些城市数据处理成级联关系的,类似如下:
[JavaScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[{
label: '一级 1',
children: [{
label: '二级 1-1',
children: [{
label: '三级 1-1-1'
}]
}]
}, {
label: '一级 2',
children: [{
label: '二级 2-1',
children: [{
label: '三级 2-1-1'
}]
}, {
label: '二级 2-2',
children: [{
label: '三级 2-2-1'
}]
}]
}]
}]
一般人的做法如下: 省、市、区三级,做三个循环,每个循环都要过滤一下,父元素ID和子元素parent_id相等的数据,当然也可以递归循环。
代码可能如下:
[JavaScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
this.shengData.forEach((item, index) => {
item.children = _tempShengData.filter(itm => itm.parent_id == item.id)
item.children.forEach(initem => {
initem.children = _tempShengData.filter(itm => itm.parent_id == initem.id)
if (initem.children.length > 0) {
initem.children.forEach(sunitem => {
sunitem.children = _tempShengData.filter(stm => stm.parent_id == sunitem.id)
})
}
})
})
//_tempShengData 是经过处理之后,去除了父级元素是0或者是空的情况的所有元素, this.shengData是后端返回的所有元素
这里最耗费性能的是循环里面还有过滤。这里消耗会很大!

优化方案

数据库查找快速方法可以建索引。那么数组可以建立类似索引的东西吗?根据上面的数组,我们可以得知,一个parent_id可能有多个子元素,我们可以建立类似key和vue形式的对象,通过对象的key,来直接获取vue值,岂不是更快?
这样就循环一次就可以了,将上面代码改进如下:
// 将所有的数据进行一个分类,key是parent_id,value是children
[JavaScript]
纯文本查看
复制代码
1
2
3
4
5
let regionObj = {}
城市数据.forEach(item => {
regionObj[item['parent_id']] = regionObj[item['parent_id']] || []
regionObj[item['parent_id']].push(item)
})
这样regionObj这个对象就是以parent_id为key,value是一个children元素的集合了。
然后再进行一次分类吧
[JavaScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
this.shengData.forEach((item, index) => {
item.children = regionObj[item.id] ? regionObj[item.id] : []
item.children.forEach(initem => {
initem.children = regionObj[initem.id] ? regionObj[initem.id] : []
if (initem.children.length > 0) {
initem.children.forEach(sunitem => {
sunitem.children = regionObj[sunitem.id] ? regionObj[sunitem.id] : []
})
}
})
})
这样比之前快了很多。
本文转自:https://www.haorooms.com/post/js_bigdataarray