JS數組關聯查找的性能優化

傳統2個數組的嵌套查詢通常經過兩個循環體嵌套實現,時間複雜度爲:n^2;
而經過創建索引對象的形式的時間複雜度爲:n;這種犧牲內存來達到複雜度降冪的的方法能提升多少性能呢?

下面是以數組1長度爲10000;數組2爲50000的亂序數組進行測試的測試結果。(測試結果的單位都是ms)javascript

Firefox測試結果: 平均快48倍java

// 第一次
傳統的嵌套循環:1479
創建索引:30
// 第二次
傳統的嵌套循環:1852
創建索引:36
// 第三次
傳統的嵌套循環:1754
創建索引:38

Chrome測試結果: 平均快64倍算法

// 第一次
傳統的嵌套循環:1800
創建索引:26
// 第二次
傳統的嵌套循環:1297
創建索引:35
// 第三次
傳統的嵌套循環:2522
創建索引:27

IE11測試結果:平均快11倍數組

// 第一次
傳統的嵌套循環:110431
創建索引:616
// 第二次
傳統的嵌套循環:7172
創建索引:689
// 第三次
傳統的嵌套循環:7310
創建索引:686

完整的代碼(實際使用中請考慮數據類型校驗和是否爲空判斷)dom

// 情景:從數組arr1的id拿到數組arr2中的全部記錄,統計急了num的總和寫回到arr1中

// 模擬2個數組
var start = 1000000
// 定義模擬2個數組的方法;count: arr1的長度值;n: 爲arr2爲arr1的長度的多少倍
function getArr(count, n) {
  var o = {
    arr1: [],
    arr2: []
  }
  for(var i = 0; i<count; i++){
    o.arr1.push({id: start+i,count: 0})
    for(var j = 0; j < n; j++){
      o.arr2.push({
        id: start + i,
        num: Math.round(Math.random()*1000)
      })
    }
  }
  // 簡單的打亂數組
  o.arr2.sort(function (a, b) {
    return a.num - b.num
  })
  return o
}


// 傳統方法的嵌套循環
function setArrCount2(o) {
  var l1 = o.arr1.length
  var l2 = o.arr2.length
  var arr1 = o.arr1
  var arr2 = o.arr2
  for(var i = 0; i < l1; i++) {
    for(var j = 0; j < l2; j++) {
      if(arr1[i].id === arr2[j].id){
        arr1[i].count += arr2[j].num
      }
    }
  }
  console.log(arr1)
  return arr1
}


// 使用降冪算法
// arr2進行分組,創建以id值爲key的對象
function getArrGroup(arr, id) {
  var o = {}
  var len = arr.length
  var index
  for(var i = 0; i < len; i++){
    index = arr[i][id]
    if(o[index]===undefined){
      o[index] = [arr[i]]
    } else {
      o[index].push(arr[i])
    }
  }
  return o
}
// 給arr1項的count賦值
function setArrCount(arr, o, fn) {
  var len = arr.length
  for(var i = 0; i < len; i++) {
    arr[i] = fn(arr, o, i)
  }
  console.log(arr)
  return arr
}

// 統計num的值
function getCount(arr) {
  var count = 0
  var len = arr.length
  for(var i = 0; i < len; i++){
    count += arr[i].num
  }
  return count
}

function someLogic(arr, o, i){
    arr[i].count = getCount(o[arr[i].id]) 
    return arr[i]
}

// 拿到2個數組
var myList = getArr(10000,5)
var myList1 = getArr(10000,5)





// 傳統方法
var st = new Date().getTime()
setArrCount2(myList1)
console.log(new Date().getTime() - st)

// 
var startTime = new Date().getTime()

var obj = getArrGroup(myList.arr2, 'id')
setArrCount(myList.arr1, obj, someLogic)
console.log(new Date().getTime() - startTime)

核心代碼:性能

// 使用降冪算法
// arr2進行分組,創建以id值爲key的對象
function getArrGroup(arr, id) {
  var o = {}
  var len = arr.length
  var index
  for(var i = 0; i < len; i++){
    index = arr[i][id]
    // 創建索引,防止覆蓋
    if(o[index]===undefined){
      o[index] = [arr[i]]
    } else {
      o[index].push(arr[i])
    }
  }
  return o
}
// 給arr1項的count賦值
function setArrCount(arr, o, id, fn) {
  var len = arr.length
  for(var i = 0; i < len; i++) {
    arr[i] = fn(arr, o, i)// fn定義處理邏輯
  }
  console.log(arr)
  return arr
}
相關文章
相關標籤/搜索