JavaScript數(shù)組去重的六種方式
一、最樸素的方法去重:雙重for循環(huán)
一想到去重,第一個(gè)就想到了雙重for循環(huán),遍歷兩層比較一下就好了,不過要注意的是,用數(shù)組的splice
刪除重復(fù)項(xiàng)后,需要將第二層循環(huán)的索引減1,不然會(huì)出現(xiàn)數(shù)組塌陷的問題。
function unique(arr) { for (let i = 0; i < arr.length; i++) { for (let j = i + 1; j < arr.length; j++) { if (arr[i] === arr[j]) { arr.splice(j, 1); j--; // 注意:由于刪除了元素,需要將 j 減一,以避免漏掉第j項(xiàng)的檢查 } } } return arr; } const arr = [1,1,2,2,3,4,4,5,5,6]; console.log(unique(arr)); // 輸出:[ 1, 2, 3, 4, 5, 6 ]
二、最省時(shí)間的去重:obj/Map存儲(chǔ) + for循環(huán)
由于對(duì)象Object
的key
值唯一,所以我們可以利用這個(gè)特性進(jìn)行去重。核心思路就是用對(duì)象
或者Map
將遍歷過的項(xiàng)作為key
存儲(chǔ)到對(duì)象或者Map
中,如果遇到已經(jīng)存在的key
,則說明出現(xiàn)了重復(fù)項(xiàng),忽略此項(xiàng)即可。
function unique(arr) { const obj = {}; // 這里可以換成Map const newArr = []; for (let i = 0; i < arr.length; i++) { const item = arr[i]; if (!obj[item]) { obj[item] = 1; newArr.push(item); } } return newArr; }
這也是典型的空間換時(shí)間大法,可以讓時(shí)間復(fù)雜度從O(n²)降為O(n),利用對(duì)象存儲(chǔ),達(dá)到空間換時(shí)間的效果,節(jié)約執(zhí)行時(shí)間。
三、最好理解的去重:indexOf + lastIndexOf
JavaScript
中提供了indexOf
和lastIndexOf
兩個(gè)方法,分別拿目標(biāo)項(xiàng)從數(shù)組的第一項(xiàng)和最后一項(xiàng)開始查找,查到了會(huì)返回對(duì)應(yīng)的索引值,如果某一項(xiàng)用indexOf
和lastIndexOf
找到的索引相同,則證明該項(xiàng)不存在重復(fù)項(xiàng),反之就存在重復(fù)項(xiàng)。
這種去重方式應(yīng)該是最好理解的。不過要注意,這里也使用了splice
,需要注意處理防止數(shù)組塌陷的問題。
function unique(arr) { for (let i = 0; i < arr.length; i++) { if (arr.indexOf(arr[i]) !== arr.lastIndexOf(arr[i])) { arr.splice(i, 1); i--; // 注意:由于刪除了元素,需要將 i 減一,以避免漏掉第i項(xiàng)的檢查 } } return arr; }
四、最簡(jiǎn)單的去重:展開運(yùn)算符 + Set
利用ES6
的新特性,也就是展開運(yùn)算符 + set應(yīng)該是最簡(jiǎn)單的去重方式,寫的字符數(shù)也是最少的。
function unique(arr) { return [...new Set(arr)]; }
五、最有趣的去重:filter + indexOf去重
利用filter
+ indeOf
其實(shí)也可以實(shí)現(xiàn)去重,而且是一行代碼搞定,非常有趣。
核心的思路就是,在用filter
遍歷時(shí),用indexOf
去查找當(dāng)前遍歷項(xiàng)的索引,如果查找到的索引與此時(shí)filter
遍歷的index
一樣,那么說明在當(dāng)前項(xiàng)之前是沒出現(xiàn)與當(dāng)前項(xiàng)相同的重復(fù)項(xiàng)的,所以該項(xiàng)需要保留
,反之則需要剔除
,而正好filter
自帶過濾功能,返回true
保留該項(xiàng),返回false
剔除該項(xiàng)。
function unique(arr) { return arr.filter((item, index) => arr.indexOf(item) === index); } const arr = [1,1,2,2,3,4,4,5,5,6]; console.log(unique(arr)); // 輸出:[ 1, 2, 3, 4, 5, 6 ]
六、最騷的去重:JSON.stringify + Set + JSON.parse
想不到吧,利用JSON.stringify
+ Set
+ JSON.parse
居然也可以實(shí)現(xiàn)去重,這應(yīng)該是最騷的去重方式了,而且天然就支持對(duì)存放數(shù)組的對(duì)象進(jìn)行去重。
去重的核心思路如下:
- 利用
JSON.stringify
可以將數(shù)組每一項(xiàng)存儲(chǔ)的對(duì)象或者普通值都進(jìn)行序列化,將原數(shù)組轉(zhuǎn)為一個(gè)字符串?dāng)?shù)組; - 利用
Set
對(duì)字符串?dāng)?shù)組進(jìn)行去重; - 利用
JSON.parse
對(duì)數(shù)組每一項(xiàng)進(jìn)行反序列化。
這里注意,如果兩個(gè)對(duì)象存的key和value都相同,則他們序列化的結(jié)果也相同,所以說這種方式是天然支持對(duì)對(duì)象進(jìn)行去重的。
function unique(arr) { return [...new Set(arr.map(t => JSON.stringify(t)))].map(s => JSON.parse(s)); } const arr = [1,1,2,2,3,4,4,5,5,6]; const arr1 = [{ a:1 }, { a:1 }, { a:2 }, { a:2 }, { a:3 }, { a:3 }, { a:4 }, { a:4 }, { a:5 }, { a:5 } ] console.log(unique(arr)); console.log(unique(arr1)); /** * 打印結(jié)果: * [ 1, 2, 3, 4, 5, 6 ] * [ { a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 } ] */
以上介紹了6種JavaScript
去重方式,我平常最常用的就是第四種,也就是展開運(yùn)算符 + Set去重,不知道大家在平時(shí)實(shí)際開發(fā)中更喜歡哪一種去重方式呢,或者還有沒有其它的更好去重方式呢?
到此這篇關(guān)于JavaScript數(shù)組去重的六種方式的文章就介紹到這了,更多相關(guān)JavaScript數(shù)組去重內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)兼容IE6的收起折疊與展開效果實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)兼容IE6的收起折疊與展開效果,結(jié)合具體實(shí)例形式分析了javascript事件響應(yīng)及針對(duì)頁面元素屬性的動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-09-09Echats圖表大屏自適應(yīng)的實(shí)現(xiàn)方法
很多時(shí)候我們需要用圖表來制作我們統(tǒng)計(jì)的數(shù)據(jù)直觀的分析,所以我們可以用Echarts來制作圖表,這篇文章主要給大家介紹了關(guān)于Echats圖表大屏自適應(yīng)的實(shí)現(xiàn)方法,需要的朋友可以參考下2021-10-10JavaScript對(duì)JSON數(shù)據(jù)進(jìn)行排序和搜索
今天教給大家如何使用數(shù)組的方法來實(shí)現(xiàn)JSON數(shù)據(jù)進(jìn)行排序和搜索功能,具體實(shí)例代碼大家參考下本文吧2017-07-07ES6?關(guān)鍵字?let?和?ES5?及關(guān)鍵字?var?的區(qū)別解析
var可以穿透控制語句、條件語句這樣的作用域,導(dǎo)致變量沖突經(jīng)常發(fā)生,這篇文章主要介紹了ES6?關(guān)鍵字?let?和?ES5?及關(guān)鍵字?var?的區(qū)別,需要的朋友可以參考下2022-09-09layui實(shí)現(xiàn)鼠標(biāo)移動(dòng)到單元格上顯示數(shù)據(jù)的方法
今天小編就為大家分享一篇layui實(shí)現(xiàn)鼠標(biāo)移動(dòng)到單元格上顯示數(shù)據(jù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09微信小程序scroll-view組件實(shí)現(xiàn)滾動(dòng)動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了微信小程序scroll-view組件實(shí)現(xiàn)滾動(dòng)動(dòng)畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01three.js中正交與透視投影相機(jī)的實(shí)戰(zhàn)應(yīng)用指南
在three.js中攝像機(jī)的作用就是不斷的拍攝我們創(chuàng)建好的場(chǎng)景,然后通過渲染器渲染到屏幕中,下面這篇文章主要給大家介紹了關(guān)于three.js中正交與透視投影相機(jī)應(yīng)用的相關(guān)資料,需要的朋友可以參考下2022-08-08關(guān)于onScroll事件在IE6下每次滾動(dòng)觸發(fā)三次bug說明
今天測(cè)試發(fā)現(xiàn)IE6下用window.onscroll,每次滾動(dòng)時(shí)會(huì)觸發(fā)3次,而火狐、IE7沒此問題,應(yīng)該是IE6的一個(gè)BUG2011-09-09js實(shí)現(xiàn)圖片輪播效果學(xué)習(xí)筆記
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)圖片輪播效果的學(xué)習(xí)筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07