《前端算法系列》數組去重

雖然算法在前端開發中不多會得以使用,可是瞭解經常使用的算法,熟悉各類算法的性能和優劣,將會讓你在前端的道路上走的更遠。前端

前言

文中全部代碼位於位於此代碼倉庫中,你們能夠下載代碼進行學習、推敲和改進。另,若是以爲這些用心推敲的代碼對你有幫助的話,歡迎 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交流學習羣,已經有數百位各企業的前端夥伴加入,歡迎你們關注 趣談前端公衆號,加入前端你們庭,一塊兒探索前端的邊界

相關文章
相關標籤/搜索