公告:携程招聘java、前端、测试、产品等,请发简历至374947554@qq.com,帮内推!

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

3096次浏览

前言

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

案例

假设后端返回数据如下:

{
    "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多个城市的数据,城市可能分为几个级别,省、市、区等等。

现在要把这些城市数据处理成级联关系的,类似如下:

[{
          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相等的数据,当然也可以递归循环。

代码可能如下:

   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

let regionObj = {}
城市数据.forEach(item => {
      regionObj[item['parent_id']] = regionObj[item['parent_id']] || []
       regionObj[item['parent_id']].push(item)
 })

这样regionObj这个对象就是以parent_id为key,value是一个children元素的集合了。

然后再进行一次分类吧

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] : []
          })
        }
      })
    })

这样比之前快了很多。

Tags: js数组大数据

相关文章: