[记录]多级数组遍历的几种方式

有一个需求:从类似下面数组中,将 id 提取出来,放入另一个数组中:

const a = [
  {
      test:[{id:1},{id:2}]
  },{
      test:[{id:3},{id:4},{id:5}]
  },{
      test:[{id:6},{id:7},{id:8}]
  },{
    test:[{id:9}]
  }
]

对于这个问题,首先我想到的是这个方案:

function convert(a){
  const b = [];
  a.forEach(v1 => {
    const tmp = [];
    v1.test.forEach(v2 => tmp.push(v2))
    b.push(...tmp)
  })
  return b;
}

如果将 forEach 换成普通的 while 循环,应该会具备更快的运行速度:

function conver2(a){  
  const b = [];
  let i = 0;
  let arrLen = a.length;
  while(i < arrLen){
    let testLen = a[i].test.length;
    let j = 0;
    while(j < testLen){
      b.push(a[i].test[j])
      j++
    }
    i++
  }
  return b;
}

冥冥之中,我感觉是可以通过一层循环来解决这个问题的,于是想出了第三种方案:

function convert3(a){
  let i = j = 0;
  let testLen = a[j].test.length;
  let arrLen = a.length;
  let b = [];

  while(j < arrLen){
    b.push(a[j].test[i].id);
    i++
    if(i == testLen){
      j++;
      i = 0
      if(j < arrLen){ 
        testLen = a[j].test.length
      }
    }
  }
  return b;
}

为了衡量三种算法的性能,需要使用较大的操作数量,于是我将代码做了一些修改,来统计这三个方法各自的执行时间:

const a = [
  {
      test:[{id:1},{id:2}]
  },{
      test:[{id:3},{id:4},{id:5}]
  },{
      test:[{id:6},{id:7},{id:8}]
  },{
    test:[{id:9}]
  }
]

for(let i = 0; i < 1000000;i ++){
  a.push(a[i % a.length])
}

function convert1(a,index){
  console.time("start-convert1-"+index);
  const b = [];
  a.forEach(v1 => {
    const tmp = [];
    v1.test.forEach(v2 => tmp.push(v2))
    b.push(...tmp)
  })
  console.timeEnd("start-convert1-"+index);
}

function convert2(a,index){
  console.time("start-convert2-"+index);
  const b = [];
  let i = 0;
  let arrLen = a.length;
  while(i < arrLen){
    let testLen = a[i].test.length;
    let j = 0;
    while(j < testLen){
      b.push(a[i].test[j])
      j++
    }
    i++
  }
  console.timeEnd("start-convert2-"+index);
}

function convert3(a,index){
  console.time("start-convert3-"+index);
  let i = j = 0;
  let testLen = a[j].test.length;
  let arrLen = a.length;
  let b = [];

  while(j < arrLen){
    b.push(a[j].test[i].id);
    i++
    if(i == testLen){
      j++;
      i = 0
      if(j < arrLen){ 
        testLen = a[j].test.length
      }
    }
  }
  console.timeEnd("start-convert3-"+index);
}

for(let i = 0; i < 10; i++){
  convert1(a,i)
  convert2(a,i)
  convert3(a,i)
}

运行结果如下:

start-convert1-0: 151.4248046875ms
start-convert2-0: 75.463134765625ms
start-convert3-0: 59.9140625ms
start-convert1-1: 133.663818359375ms
start-convert2-1: 54.760986328125ms
start-convert3-1: 58.22607421875ms
start-convert1-2: 135.48095703125ms
start-convert2-2: 56.72314453125ms
start-convert3-2: 53.788818359375ms
start-convert1-3: 147.720703125ms
start-convert2-3: 58.44091796875ms
start-convert3-3: 54.409912109375ms
start-convert1-4: 143.4169921875ms
start-convert2-4: 55.30810546875ms
start-convert3-4: 51.42578125ms
start-convert1-5: 144.20703125ms
start-convert2-5: 57.093017578125ms
start-convert3-5: 51.152099609375ms
start-convert1-6: 143.78076171875ms
start-convert2-6: 54.94775390625ms
start-convert3-6: 51.739013671875ms
start-convert1-7: 147.794921875ms
start-convert2-7: 57.3330078125ms
start-convert3-7: 54.512939453125ms
start-convert1-8: 148.298095703125ms
start-convert2-8: 55.76806640625ms
start-convert3-8: 54.154052734375ms
start-convert1-9: 153.4873046875ms
start-convert2-9: 54.783203125ms
start-convert3-9: 55.839111328125ms

在十次的测试中,第三种方法的成绩最好,其次是第二种方式,但二者差距不大。使用 forEach 的第一种方法性能最差。抽象级别越高的方法,性能越弱。

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容