溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript數(shù)組怎么去重

發(fā)布時間:2020-12-03 13:15:46 來源:億速云 閱讀:168 作者:小新 欄目:web開發(fā)

這篇文章將為大家詳細講解有關JavaScript數(shù)組怎么去重,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

數(shù)組去重在日常開發(fā)中的使用頻率還是較高的,也是網上隨便一抓一大把的話題,所以,我寫這篇文章目的在于歸納和總結,既然很多人都在提的數(shù)組去重,自己到底了解多少呢。又或者是如果自己在開發(fā)中遇到了去重的需求,自己能想到更好的解決方案嗎。

這次我們來理一理怎么做數(shù)組去重才能做得最合適,既要考慮兼容性,也要考慮性能和代碼的優(yōu)雅。

我的學習路徑是模仿冴羽(github: mqyqingfeng)的學習方式,感謝像冴羽這樣優(yōu)秀的人在前面領跑,我不想光看不做,所以多實踐多輸出,希望未來能走出我自己的路。

一、入門方案
function unique(origin) {
    var result = [];
    for(var i = 0; i < origin.length; i++) {
        var arrayItem = origin[i];

        for(var j= 0; j< result.length; j++) {
            var resultItem = result[j];
            
            // 如果在結果數(shù)組循環(huán)中找到了該元素,則跳出循環(huán),進入下一個源數(shù)組元素的判斷
            if(resultItem === arrayItem) {
                break;
            }
        }
        
        // 如果把結果數(shù)組循環(huán)完都沒有找到該元素,就將該元素壓入結果數(shù)組中
        if(j === result.length) {
            result.push(arrayItem);
        }
    }
    return result;
}

var array = ['a', 'b', 'c', '1', 0, 'c', 1, '', 1, 0];
console.log(unique(array));  // ["a", "b", "c", "1", 0, 1, ""]

以上代碼是最簡單實現(xiàn)數(shù)組去重的方式,優(yōu)點在于兼容性極好,缺點就是兩次 for 循環(huán),時間復雜度為 O(n^2),性能較差。

二、數(shù)組的 indexOf 屬性

數(shù)組中的 indexOf 屬性是 ES5 的規(guī)范,只有 IE8 及更早版本不支持該方法。相對來說,如果你不需要兼容 IE8 的話,盡量用 indexOf 來判斷一個元素是否在數(shù)組中。

function unique(origin){
    var result = [];
    for(var i = 0; i< origin.length; i++) {
        var item = origin[i];
        if(result.indexOf(item) === -1) {
            result.push(item);
        }
    }
    return result;
}
三、數(shù)組的 filter 屬性
數(shù)組的 filter() 方法創(chuàng)建一個新的數(shù)組,新數(shù)組中的元素是通過檢查指定數(shù)組中符合條件的所有元素。

filter 的回調有三個參數(shù),其中第三個參數(shù)是當前元素屬于的數(shù)組對象,這樣我們可以繼續(xù)利用 indexOf 屬性啦。

function unique(origin) {
    var result = origin.filter(function (item, index, array){
        // 獲取元素在源數(shù)組的位置,只返回那些索引等于當前元素索引的值。
        return array.indexOf(item) === index;
    });
    return result;
}

filter 兼容到 IE9, 這種方法沒有 for 循環(huán),主要利用了 filter 和 indexOf 屬性,所以代碼相對比較優(yōu)雅。

四、利用 Object 的 key value
function unique(origin) {
    var result = [];
    var hashTable = {};
    for(var i = 0; i< origin.length; i++) {
        // 如果鍵對應的值,為真,意味著對象的鍵中已經有重復的鍵了。
        if(!hashTable[origin[i]]) {
        // 將元素作為對象的鍵,默認鍵對應的值為 true, 
            hashTable[origin[i]] = true;
            
            // 如果對象中沒有這個鍵,則將這個元素放入結果數(shù)組中去。
            result.push(origin[i]);
        }
    }
    return result;
}

這種方案的事件復雜度為 O(n), 但是對象的鍵,默認是字符串類型,這意味著什么呢,數(shù)字 1 和 字符串 '1',在鍵中是相等的,所以,上面這種方法不適合字符串和數(shù)字混合的去重。

所以我們將元素的類型也放入對象的鍵中:

function unique(origin) {
    var result = [];
    var hashTable = {};
    for(var i = 0; i< origin.length; i++) {
        var current = origin[i];
        // 字符串拼接元素的類型和元素
        var key = typeof(current) + current;
        if(!hashTable[key]) {
            hashTable[key] = true;
            result.push(current);
        }
    }
    return result;
}
五、數(shù)組的 sort 方法
function unique(origin) {
    return origin.concat.sort().filter(function(item, index, array) {
        // !index 表示第 0 個元素應該被返回。
        return !index || item !== origin[index-1]
    })
}

function unique(array) {
    array.sort(); // 排序字符串
    array.sort(function(a, b) {
        return a-b; // 排序數(shù)字
    })
    
    for(let i=0; i<array.length; i++) {
        if(array[i] === array[i+1]) {
            array.splice(i, 1);
            i--; // 應該將前一個數(shù)刪除,而不是刪除后一個數(shù)。是因為元素被刪除之后,后面元素的索引會遷移,所以要 i--;
        }
    }
    return array;
}

sort 方法的優(yōu)點在于利用了排序,返回后一個和前一個不相等的元素。比較簡潔和直觀。缺點在于改變了元素的本來的排序位置。

六、ES6 Set

ES6 提供了新的數(shù)據(jù)結構 Set,它類似于數(shù)組,但是成員的值都是唯一的,沒有重復的值。向 Set 加入值的時候,不會發(fā)生類型轉變,所以 5 和 '5' 是兩個不同的值。Set內部判斷兩個值是否相同,用的是類似于 "==="的算法,但是區(qū)別是,在set內部認為NaN 等于 NaN ;

Set 可以轉換為數(shù)組,所以很容易實現(xiàn)去重

function unique(origin) {
    return Array.from(new Set(origin));
}
七、ES6 Map

ES6 新增了 Map 數(shù)據(jù)結果,通過 has 和 set 方法就能很方便的對前面的 object key value 方案進行優(yōu)化。

function unique(origin){
    const map = new Map()
    return origin.filter((item) => !map.has(item) && map.set(item, true))
}
八、類型判斷

一些常見的數(shù)據(jù)類型是 ===indexOf 是無法檢測的,舉個例子:

console.log({} === {})  // false;

console.log(NaN === NaN)  // false;

console.log(/a/ === /a/);  // false;

console.log(1 === new String('1'))  // false;

var arr = [NaN];
console.log(arr.indexOf(NaN)); // -1

所以在判斷的時候,如果數(shù)據(jù)里有 NaN 和對象時要避免使用 indexOf===;

前面 Set 那里說過了,所以 Set 方法是可以去重 NaN的。

關于JavaScript數(shù)組怎么去重就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI