传统2个数组的嵌套查询一般通过两个循环体嵌套实现,时间复杂度为:n^2;
而通过建立索引对象的形式的时间复杂度为:n;这种牺牲内存来达到复杂度降幂的的方法能提高多少性能呢?

下面是以数组1长度为10000;数组2为50000的乱序数组进行测试的测试结果。(测试结果的单位都是ms)

Firefox测试结果: 平均快48倍

// 第一次
传统的嵌套循环:1479
建立索引:30
// 第二次
传统的嵌套循环:1852
建立索引:36
// 第三次
传统的嵌套循环:1754
建立索引:38

Chrome测试结果: 平均快64倍

// 第一次
传统的嵌套循环:1800
建立索引:26
// 第二次
传统的嵌套循环:1297
建立索引:35
// 第三次
传统的嵌套循环:2522
建立索引:27

IE11测试结果:平均快11倍

// 第一次
传统的嵌套循环:110431
建立索引:616
// 第二次
传统的嵌套循环:7172
建立索引:689
// 第三次
传统的嵌套循环:7310
建立索引:686

完整的代码(实际使用中请考虑数据类型校验和是否为空判断)

// 情景:从数组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
}

SmartCoder
971 声望827 粉丝

可怕的是:不甘于平庸,又不去努力。