• Javascript系列——对象元素的数组去重实现


    概要

    这是一篇记录文,记录数组操作对象去重的实现。

    需求

    有这样一个数组

    
    [{
        _id: 123,
        name: '张三'
    },{
        _id: 124,
        name: '李四'
    },{
        _id: 123,
        name: '张三'
    }]
    

    实际上我们只需要

    
    [{
        _id: 123,
        name: '张三'
    },{
        _id: 124,
        name: '李四'
    }]
    

    去重

    简单数组的去重

    
    Array.from(new Set([1,1,2,3,4,4])) // [1,2,3,4]
    

    以对象为元素的数组去重

    和数组相关的算法多种多样,在你以为自己已经掌握数组之后,会发现很多和数组相关的算法仍旧很复杂。

    下面我将讲述一个入门等级的数组算法,解决上面提出的需求。

    1、定义一个函数removeRepeat,它需要传入2个参数,arr表示需要去重的数组,field表示需要比较的key。比如我们的需求是比较 _id 是否有重复。

    
    function removeRepeat(arr, field){
        return arr
    }
    

    2、需要一个空数组,用来存储每个对象元素中field对应的value。

    
    let s = []
    for(let v of arr){
        s.push(v[field])
    }
    //s = [123, 124, 123]
    

    3、将所有field的值存到数组之后,它们的下标一一对应原数组的下标(这点很重要),接着我们需要2个对象集合,result用来存储s里遍历出来的元素,如果有重复,就将重复的元素丢到reSet对象里面。

    
    let result = {}, reSet = {}
    for(let i=0,len=s.length;i<len;i++){
        if(!result[s[i]] && result[s[i]] !== 0) {
        //如果result不存在当前的key并且它不为0时
           result[s[i]] = i
        } else {
          reSet[s[i]] = i
        }
    }
    // result = {123: 0, 124: 1} 这是去重重复后的元素
    // reSet = {123: 2} 我们将重复的元素123作为key,它的下标2作为value。
    

    4、上一步得到了result和reSet2个对象,那么,我们该用哪个对象来处理原数组的去重呢?只需要reSet,reSet记录了要去重的对象所在的下标,那么可以直接用splice干掉它。

    
    for(let key in reSet){
        arr.splice(reSet[key], 1)
    }
    /* 
    arr = [{
        _id: 123,
        name: '张三'
    },{
        _id: 124,
        name: '李四'
    }]
    */
    

    5、说明

    关键的第3和4步,都是用对象来处理,这样做的好处是时间复杂度可以达到O(1),如果用数组来保存,则需要2个for循环,时间复杂度变成了O(n²)。

    完整源码

    
    function removeRepeat(arr, field){
        let s = [], result = {}, reSet = {}
        for(let v of arr){
            s.push(v[field])
        }
        for(let i=0,len=s.length;i<len;i++){
            if(!result[s[i]] && result[s[i]] !== 0) {
               result[s[i]] = i
            } else {
              reSet[s[i]] = i
            }
        }
        for(let key in reSet){
            arr.splice(reSet[key], 1)
        }
        return arr
    }
    
    // removeRepeat(arr, '_id')
    

    补充

    受到各路大神的解法影响,我也针对上面代码的不足做了修改。

    1、更简洁的代码。

    2、支持多个重复对象的去重,缺点是会改变原来的排序。

    
    const removeRepeat = (arr, field) => {
        let s = {}
        for(let i=0,len=arr.length;i<len;i++){
            s[arr[i][field]] = arr[i]
        }
        return Object.values(s)
    }
    

    总结

    数组还有各种有趣的操作,也经常作为各大公司考察的题型之重,多练习和数组相关的算法会很有帮助。

    原文地址:https://segmentfault.com/a/1190000012873968

  • 相关阅读:
    Linux bash sh .source exec 的区别比较。
    flink1.10 Linux 集群安装
    有关Spark中FlatMap算子源码理解
    Flink有关于水位线(WaterMark)相关问题
    Flink中并行度相关问题
    关于spark中的ResultStage和ShuffleMapStage
    关于windows10共享WiFi问题
    外网映射
    Druid的问题
    《小学四则运算练习软件软件需求说明》结对项目报告
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9959426.html
Copyright © 2020-2023  润新知