• 你真的会数组去重吗?去重方法汇总解析,看着一篇就够了


    去重方法

    在平时敲代码时,经常会遇到需要对数组进行去重的情况,若两个数组较小,此时使用任何一种去重方式都不会对效率产生太大影响,但当数组较大时,好的去重方法会明显提高运行效率。
    此外,去重方法也经常出现在各类面试笔试题中,为此我总结了一下各种去重方法,供大家参考。

    双重for循环

    这种方法是最直观最容易想到的了,代码如下:

       let arr = [
          {id: 1, name: 'lsm'},
          {id: 2, name: 'mjl'},
          {id: 1, name: 'lsm'}
        ]
        for (let i = 0; i < arr.length; i++) {
          for (let j = i + 1; j < arr.length; j++) {
            if (arr[i].id === arr[j].id) {
              arr.splice(j, 1)
              j--
            }
          }
        }
        console.log('arr--', arr)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    实现起来简单直观,但代码量大且效率低下,不够优雅。

    forEach+findindex实现去重

    利用findIndex 查找元素,根据返回结果组建最终结果数组,这样就优雅多了。

       let arr1 = [
          {id: 1, name: 'lsm'},
          {id: 2, name: 'mjl'},
          {id: 1, name: 'lsm'}
        ]
        let newArr1 = []
        arr1.forEach((item, index) => {
         arr1.findIndex(el => el.id == item.id) == index && newArr1.push(item)
        })
    
        console.log('newArr1', newArr1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    findIndex作用:找到遍历的数组中的第一个符合判断条件的值,并返回该值对应的索引。
    代码解析:

    1. 首先定义输出数组newArr1;
    2. 使用forEach遍历arr1,拿到其中的每个对象并使用findIndex查找此元素在arr1中第一次出现的index值。
    3. 当外层循环index值等于findIndex返回的index值时,表明此值第一次出现,则push到newArr1中。
    4. 如果外层循环index值bu等于findIndex返回的index值时,则表明此值不是第一次出现,则不push到newArr1中。

    filter+findIndex实现去重

    forEach+findindex方法的变种,代码如下:

    let arr2 = [
      {id: 1, name: 'lsm'},
      {id: 2, name: 'mjl'},
      {id: 1, name: 'lsm'}
    ]
    arr2 = arr2.filter((item, index) => {
      return arr2.findIndex(el => el.id == item.id) == index
    })
    console.log('arr3--', arr2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这种方式,和forEach+findindex方式原理相同,我就不解释了。

    forEach搭配some实现去重

    针对的是由基本数据类型组成的数组,我们只要遍历一层,搭配indexOf、includes等方法,就可以实现去重,代码如下:

       let arr = [ 1, 1, 1, "1", "lsm", "52", 2, 81, 2, 81]
        let newArr = []
        arr.map((item, index) => {
          //!newArr.includes(item) && newArr.push(item)
          newArr.indexOf(arr1[i]) === -1 && newArr.push(arr1[i])
        })
        console.log('newArr--', newArr)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果数组内是引用类型的参数,在indexOf、includes无法使用时,可以使用some作为替代,上代码:

     let arr3 = [
          {id: 1, name: 'lsm'},
          {id: 2, name: 'mjl'},
          {id: 1, name: 'lsm'}
        ]
        let newArr3 = []
        arr3.forEach((item, index) => {
          !newArr3.some(el => el.id == item.id)  && newArr3push(item)
        })
        console.log('newArr2', newArr2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    some作用:判断数组中是否存在满足条件的值,如果有则返回true,完整遍历不会终止循环,可以使用return自行终止(此例中并没用到该特性)

    filter和find

    此方法仍然为filter+findIndex的变种,使用find替代findIndex,代码如下:

    let arr4 = [
          {id: 1, name: 'lsm'},
          {id: 2, name: 'mjl'},
          {id: 1, name: 'lsm'}
        ]
        arr4 = arr4.filter(item => {
          return arr4.find(el => el.id == item.id) == item
        })
        console.log('arr4', arr4)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    find返回的是符合条件的遍历项,需要注意的是,这里不推荐使用find,因为find方法比较的是引用地址,如果数组中的对象地址出现相同的情况则达不到去重效果,如:

    let obj = {id: 10, name: 'lsm'}
    let arr = []
    arr.push(obj)
    arr.push(obj)
    //arr中的两个对象引用地址实际上是一样
    //Set不能对对象去重,但是这种情况可以
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    find作用:找出符合判断条件的第一项,并进行返回

    map结合some | find | findexIndex

    最终总结:

    1. 引用类型的数组要进行去重操作,主要实现的方式为双重循环。
    2. 外层循环可以是forEach、map等方法,为内层循环提供去重对象。
    3. 内层循环借用各类函数实现去重,内层使用的函数需要有返回值用于判断是否重复,可以是some,findIndex,find等。
      最后将map和some、find、findexIndex方法汇总一下:
    let arr5 = [
      {id: 1, name: 'lsm'},
      {id: 2, name: 'mjl'},
      {id: 1, name: 'lsm'}
    ]
    let newArr5 = []
    arr5.map((item, index) => {
      // !newArr5.some(el => el.id == item.id) && newArr5.push(item)
      // arr5.findIndex(el => el.id === item.id) === index && newArr5.push(item)
      arr5.find(el => el.id === item.id) === item && newArr5.push(item)
    })
    console.log('arr5', newArr5)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    作者简介 :游逸,高级软件工程师,7年开发经验,喜欢分享干货与关注技术前沿,欢迎一起交流学习

  • 相关阅读:
    cs231n_1_IntroToConv
    封装自己的本地缓存类(单例模式、适配器模式应用)
    笔记--autosar是什么
    怎么样子盒子能撑起父盒子?浮动,BFC,边距重叠
    浅析C++内存布局
    【TUM公开数据集RGBD-Benchmark工具evaluate_ate.py参数用法原理解读】
    Maven下载及相关配置附IDEA更换本地Maven
    原生Js 提取视频中的音频
    Splunk Workflow action 给我们带来的好处
    智安网络|揭开云服务的神秘面纱:其含义和功能的综合指南
  • 原文地址:https://blog.csdn.net/talenter111/article/details/126261590