摘要:將元素作為對象的鍵,默認鍵對應的值為如果對象中沒有這個鍵,則將這個元素放入結果數組中去。
前言
數組去重在日常開發中的使用頻率還是較高的,也是網上隨便一抓一大把的話題,所以,我寫這篇文章目的在于歸納和總結,既然很多人都在提的數組去重,自己到底了解多少呢。又或者是如果自己在開發中遇到了去重的需求,自己能想到更好的解決方案嗎。
這次我們來理一理怎么做數組去重才能做得最合適,既要考慮兼容性,也要考慮性能和代碼的優雅。
我的學習路徑是模仿冴羽(github: mqyqingfeng)的學習方式,感謝像冴羽這樣優秀的人在前面領跑,我不想光看不做,所以多實踐多輸出,希望未來能走出我自己的路。
一、入門方案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]; // 如果在結果數組循環中找到了該元素,則跳出循環,進入下一個源數組元素的判斷 if(resultItem === arrayItem) { break; } } // 如果把結果數組循環完都沒有找到該元素,就將該元素壓入結果數組中 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, ""]
以上代碼是最簡單實現數組去重的方式,優點在于兼容性極好,缺點就是兩次 for 循環,時間復雜度為 O(n^2),性能較差。
二、數組的 indexOf 屬性數組中的 indexOf 屬性是 ES5 的規范,只有 IE8 及更早版本不支持該方法。相對來說,如果你不需要兼容 IE8 的話,盡量用 indexOf 來判斷一個元素是否在數組中。
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; }三、數組的 filter 屬性
數組的 filter() 方法創建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素。
filter 的回調有三個參數,其中第三個參數是當前元素屬于的數組對象,這樣我們可以繼續利用 indexOf 屬性啦。
function unique(origin) { var result = origin.filter(function (item, index, array){ // 獲取元素在源數組的位置,只返回那些索引等于當前元素索引的值。 return array.indexOf(item) === index; }); return result; }
filter 兼容到 IE9, 這種方法沒有 for 循環,主要利用了 filter 和 indexOf 屬性,所以代碼相對比較優雅。
四、利用 Object 的 key valuefunction unique(origin) { var result = []; var hashTable = {}; for(var i = 0; i< origin.length; i++) { // 如果鍵對應的值,為真,意味著對象的鍵中已經有重復的鍵了。 if(!hashTable[origin[i]]) { // 將元素作為對象的鍵,默認鍵對應的值為 true, hashTable[origin[i]] = true; // 如果對象中沒有這個鍵,則將這個元素放入結果數組中去。 result.push(origin[i]); } } return result; }
這種方案的事件復雜度為 O(n), 但是對象的鍵,默認是字符串類型,這意味著什么呢,數字 1 和 字符串 "1",在鍵中是相等的,所以,上面這種方法不適合字符串和數字混合的去重。
所以我們將元素的類型也放入對象的鍵中:
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; }五、數組的 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; // 排序數字 }) for(let i=0; isort 方法的優點在于利用了排序,返回后一個和前一個不相等的元素。比較簡潔和直觀。缺點在于改變了元素的本來的排序位置。
六、ES6 SetES6 提供了新的數據結構 Set,它類似于數組,但是成員的值都是唯一的,沒有重復的值。向 Set 加入值的時候,不會發生類型轉變,所以 5 和 "5" 是兩個不同的值。Set內部判斷兩個值是否相同,用的是類似于 "==="的算法,但是區別是,在set內部認為NaN 等于 NaN ;
Set 可以轉換為數組,所以很容易實現去重
function unique(origin) { return Array.from(new Set(origin)); }七、ES6 MapES6 新增了 Map 數據結果,通過 has 和 set 方法就能很方便的對前面的 object key value 方案進行優化。
function unique(origin){ const map = new Map() return origin.filter((item) => !map.has(item) && map.set(item, true)) }八、類型判斷一些常見的數據類型是 === 和 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所以在判斷的時候,如果數據里有 NaN 和對象時要避免使用 indexOf 和 ===;
前面 Set 那里說過了,所以 Set 方法是可以去重 NaN的。
總結數據去重在網上已經看煩了,但還是想專門寫一篇文章來實踐和總結,能在工作中多幾個思路也是極好的。感謝那些熱愛分享和喜歡輸出的人。
歡迎關注我的個人公眾號“謝南波”,專注分享原創文章。
掘金專欄 JavaScript 系列文章JavaScript之變量及作用域
JavaScript之聲明提升
JavaScript之執行上下文
JavaScript之變量對象
JavaScript之原型與原型鏈
JavaScript之作用域鏈
JavaScript之閉包
JavaScript之this
JavaScript之arguments
JavaScript之按值傳遞
JavaScript之例題中徹底理解this
JavaScript專題之模擬實現call和apply
JavaScript專題之模擬實現bind
JavaScript專題之模擬實現new
JS專題之事件模型
JS專題之事件循環
JS專題之去抖函數
JS專題之節流函數
JS專題之函數柯里化
JS專題之數組去重
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108916.html
摘要:專題系列共計篇,主要研究日常開發中一些功能點的實現,比如防抖節流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數組合專題系列第十六篇,講解函數組合,并且使用柯里化和函數組合實現模式需求我們需要寫一個函數,輸入,返回。 JavaScript 專題之從零實現 jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現一個 jQuery 的 ext...
距離上次發文,已經有一段時間了,最近工作比較忙,這不眼看快雙十一了,就相當于給大家一些福利吧! showImg(https://segmentfault.com/img/remote/1460000016538082?w=250&h=250); 一、什么是數組去重 簡單說就是把數組中重復的項刪除掉,你 GET 到了嗎 ?下面我將簡單介紹下幾種基本的方法及其優缺點。 二、方法匯總 兩層循環 無相同...
摘要:寫在前面專題系列是我寫的第二個系列,第一個系列是深入系列。專題系列自月日發布第一篇文章,到月日發布最后一篇,感謝各位朋友的收藏點贊,鼓勵指正。 寫在前面 JavaScript 專題系列是我寫的第二個系列,第一個系列是 JavaScript 深入系列。 JavaScript 專題系列共計 20 篇,主要研究日常開發中一些功能點的實現,比如防抖、節流、去重、類型判斷、拷貝、最值、扁平、柯里...
摘要:專題系列第三篇,講解各種數組去重方法,并且跟著寫一個前言數組去重方法老生常談,既然是常談,我也來談談。它類似于數組,但是成員的值都是唯一的,沒有重復的值。 JavaScript 專題系列第三篇,講解各種數組去重方法,并且跟著 underscore 寫一個 unique API 前言 數組去重方法老生常談,既然是常談,我也來談談。 雙層循環 也許我們首先想到的是使用 indexOf 來循...
閱讀 2577·2021-11-25 09:43
閱讀 1848·2021-09-22 15:26
閱讀 3695·2019-08-30 15:56
閱讀 1702·2019-08-30 15:55
閱讀 1889·2019-08-30 15:54
閱讀 805·2019-08-30 15:52
閱讀 3135·2019-08-29 16:23
閱讀 886·2019-08-29 12:43