《前端算法系列》数组去重

虽然算法在前端开发中不多会得以使用,可是了解经常使用的算法,熟悉各类算法的性能和优劣,将会让你在前端的道路上走的更远。前端

前言

文中全部代码位于位于此代码仓库中,你们能够下载代码进行学习、推敲和改进。另,若是以为这些用心推敲的代码对你有帮助的话,欢迎 star 一下代码仓库,众筹博主的小星星。vue

另外,本文中使用以下函数对代码进行性能测试:node

module.exports = async function getFnRunTime(fn) {
    let startTime = Date.now(), endTime;
    let result = await fn();
    endTime = Date.now();
    console.log(`total time:${endTime-startTime}ms`,
                'test array\'length:' + len, result.length ); } 复制代码

为了衡量性能,咱们引入代码时间复杂度的概念,用大写O()来表现算法时间复杂度的记法,咱们称之为大O记法。通常状况下,随着n的增大,T(n)增加最慢的算法为最优算法。react

1.双重for循环去重

若是有相同的值则跳过,不相同则push进数组git

function distinct1(arr = testArr) {
    let result = [],
           len = arr && arr.length;
    for (let i=0; i< len; i++) {
        for (let j=i+1; j< len; j++) {
            if (arr[i] === arr[j]) {
                j = ++i;
            }
        }
        result.push(arr[i])
    }
    return result
}
复制代码

因为使用了双层for循环,根据代码可知时间复杂度为O(n^2),用测试函数测的19815条数据的去重时间为:7-8ms;es6

2.利用indexOf和forEach/for循环去重

function distinct2(arr = testArr) {
    let result = [];
    arr.forEach((v, i, array) => {
        array.indexOf(v, i+1) === -1 && result.push(v)
    });
    return result
}
复制代码

能够看到该方法的代码很简洁,时间复杂度为O(n),可是indexOf会进行额外的性能消耗,测试相同的数据耗时为:4-5msgithub

3.对象法

经过利用对象建名的惟一性去去重算法

function distinct3(arr = testArr) {
    let result = [], resultObj = {}, len = arr.length;
    for(let i=0; i< len; i++) {
        let val = arr[i],
           type = typeof val;
        if(!resultObj[val]) {
            result.push(val);
            resultObj[val] = [type];
        } else if(!resultObj[val].indexOf(type) < 0) {
            result.push(val);
            resultObj[val] = [type];
        }
    }
    return result
}
复制代码

该方法很快,时间复杂度为O(n),可是因为会多建立一个对象,会带来额外的内存开销,尤为是数据量大的情景下,测试相同的数据耗时为:5ms小程序

4.filter去重方法一

利用filter和indexOf来查询数组

function distinct4(arr = testArr) {
    return arr.filter((v, i, array) => array.indexOf(v, i+1) < 0)
}
复制代码

该方法也很简洁,测试相同的数据耗时为:4-5ms,关键优化点是利用indexOf的第二个参数去避免没必要要的查询。

5.filter去重方法二

和方法4的区别是利用数组的索引的惟一性来去重

function distinct5(arr = testArr) {
    return arr.filter((v, i, array) => array.indexOf(v) === i)
}
复制代码

该方法同4,可是性能远不如方法4,由于数组每次调用indexOf都会从新查找整个数组,但这是必需要作的操做,不然就不能利用数组索引的惟一性了。耗时:16ms(小伙伴们都惊呆了)

6.利用es6的set方法

function distinct6(arr = testArr) {
    return [...new Set(arr)]
}
复制代码

此方法耗时1ms,可是局限性很大,针对相同类型的数据很快,可是不一样类型的数据去重,将很是慢,这涉及到js相关的底层知识,这里就先不介绍了,后期须要的话能够专门上一篇文章介绍~

好啦,其实数组去重有不少种方法,只有你想不到的,没有实现不了的,若是你有更好更快的方法,欢迎一块儿交流探讨哦~

咱们组建的vue-react-小程序-node交流学习群,已经有数百位各企业的前端伙伴加入,欢迎你们关注 趣谈前端公众号,加入前端你们庭,一块儿探索前端的边界

相关文章
相关标签/搜索