公告:攜程招聘java、前端、測試、產品等,請發簡歷至[email protected],幫內推!

js處理大數據數組循環的一些性能優化

441次瀏覽

前言

上一節我寫了觀察者模式,是一種設計模式。這些設計模式就是一些思路。當然,關于排序,有快速排序法,關于查找有二分查找法等等,這些都為我們提供了一些思路。那么對于避免不了的大數據循環,分類,查找,有什么更加提高性能,或者說是降低內存消耗的方法嗎?

案例

假設后端返回數據如下:

{
    "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數組大數據

相關文章:

任选9场吧