javascript数组去重的几种方法

数组(包含对象等类型元素)去重

解决思路

一个数组(包含对象等类型元素)去重函数,需要在基础类型判断相等条件下满足以下条件:

  • 如果元素是数组类型,则需要数组中的每一项相等
  • 如果元素是对象类型,则需要对象中的每个键值对相等

去重本身就是遍历数组,然后比较数组中的每一项是否相等而已,所以关键步骤有两步:比较、去重

比较

  1. 首先判断类型是否一致,类型不一致则返回认为两个数组元素是不同的,否则继续
  2. 如果是数组类型,则递归比较数组中的每个元素是否相等
  3. 如果是对象类型,则递归比较对象中的每个键值对是否相等
  4. 否则,直接 === 比较

去重

  • 采用 reduce 去重,初始accumulator(累加器)为 [ ]
  • 采用findIndex找到 accumulator 是否包含相同元素,如果不包含则加入,否则不加入
  • 返回最终的accumulator,则为去重后的数组
// 获取类型
const getType = (function() {
    
    
    const class2type = {
    
     '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', '[object Function]': 'function', '[object Array]': 'array', '[object Date]': 'date', '[object RegExp]': 'regexp', '[object Object]': 'object', '[object Error]': 'error', '[object Symbol]': 'symbol' }

    return function getType(obj) {
    
    
        if (obj == null) {
    
    
            return obj + ''
        }
        // javascript高级程序设计中提供了一种方法,可以通用的来判断原始数据类型和引用数据类型
        const str = Object.prototype.toString.call(obj)
        return typeof obj === 'object' || typeof obj === 'function' ? class2type[str] || 'object' : typeof obj
    };
})();

/**
 * 判断两个元素是否相等
 * @param {any} o1 比较元素
 * @param {any} o2 其他元素
 * @returns {Boolean} 是否相等
 */
const isEqual = (o1, o2) => {
    
    
    const t1 = getType(o1)
    const t2 = getType(o2)

    // 比较类型是否一致
    if (t1 !== t2) return false
    
    // 类型一致
    if (t1 === 'array') {
    
    
        // 首先判断数组包含元素个数是否相等
        if (o1.length !== o2.length) return false 
        // 比较两个数组中的每个元素
        return o1.every((item, i) => {
    
    
            // return item === target
            return isEqual(item, o2[i])
        })
    }

    if (t2 === 'object') {
    
    
        // object类型比较类似数组
        const keysArr = Object.keys(o1)
        if (keysArr.length !== Object.keys(o2).length) return false
        // 比较每一个元素
        return keysArr.every(k => {
    
    
            return isEqual(o1[k], o2[k])
        })
    }

    return o1 === o2
}

// 数组去重
const removeDuplicates = (arr) => {
    
    
    return arr.reduce((accumulator, current) => {
    
    
        const hasIndex = accumulator.findIndex(item => isEqual(current, item))
        if (hasIndex === -1) {
    
    
            accumulator.push(current)
        }
        return accumulator
    }, [])
}

// 测试
removeDuplicates([123, {
    
    a: 1}, {
    
    a: {
    
    b: 1}}, {
    
    a: "1"}, {
    
    a: {
    
    b: 1}}, "meili", {
    
    a:1, b:2}, {
    
    b:2, a:1}])
// [123, {a: 1}, a: {b: 1}, {a: "1"}, "meili", {a: 1, b: 2}]

不产生新数组,删除数组里的重复元素

即在原有的数组上进行去重操作

排序去重

sort() 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的

const removeDuplicates = (nums) => {
    
    
    // 原地排序
    nums.sort()
    // 去重
    let len = 1
    for (let i = 1; i < nums.length; i++)
        if (nums[i] != nums[i-1]) nums[len++] = nums[i];
    // 删除重复项
    nums.splice(len)
    return nums
}

// 测试
removeDuplicates([1, 2, 3, 1, 3])
// [1, 2, 3]

优化

const removeDuplicates = (nums) => {
    
    
    let len = nums.length - 1
    for(let i = len; i>=0; i--) {
    
    
        if(nums.indexOf(nums[i]) != i) {
    
    
            nums[i] = nums[len --]
        }
    }
    // 删除重复项
    nums.splice(len+1)
    return nums
}
// 测试
removeDuplicates([1, 2, 3, 1, 3])
// [1, 2, 3]

产生一个新数组,进行去重

Set(ES6中的方法)

function remove(arr) {
    
    
    return Array.from(new Set(arr))
}
// 或者
var remove = arr => [...new Set(arr)]

// 测试
var arr = [1, 2, 2, 3]
remove(arr); // [1, 2, 3]

reduce

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

reduce() 可以作为一个高阶函数,用于函数的 compose。

function remove (arr) {
    
    
    return arr.sort().reduce((acc, cur) => {
    
    
     if (acc.length === 0 || acc[acc.length - 1] !== cur) {
    
    
         acc.push(cur);
     }
     return acc
 }, [])}
;

// 测试
var arr = [1, 2, 2, 3]
remove(arr); // [1, 2, 3]

filter

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

function remove(arr) {
    
     
    return arr.filter( (element, index, array) => {
    
    
     return array.indexOf(element) === index
 })
}

// 测试
var arr = [1, 2, 2, 3]
remove(arr); // [1, 2, 3]

猜你喜欢

转载自blog.csdn.net/PILIpilipala/article/details/113444874