JavaScript中數(shù)組去重的辦法總結(jié)
前言
你是否在面試的過(guò)程中被考到過(guò)給你一個(gè)數(shù)組讓你去掉重復(fù)項(xiàng)呢?當(dāng)時(shí)你的腦海里除了用Set實(shí)現(xiàn)之外,你還與面試官講了什么去重的方法呢?你能否封裝來(lái)一個(gè)可復(fù)用的數(shù)組去重api呢?依稀記得當(dāng)時(shí)我被問(wèn)到這個(gè)問(wèn)題的時(shí)候,我也沒(méi)回答出很多種解決辦法。那下面我來(lái)總結(jié)一下對(duì)于數(shù)組去重這道簡(jiǎn)單的面試題時(shí),我們可以回答的方法有什么吧。
數(shù)組去重
1. 不使用數(shù)組API方法
首先我來(lái)介紹一種不是用數(shù)組身上的API的去重解法,代碼如下:
var array = ['1', 1, '1', '1', '2', 2] function unique(array) { let res = [] for(let i = 0; i < array.length; i++){ for( var j = 0; j < res.length; j++){ if(array[i] === res[j]){ break; } } if(j === res.length){ res.push(array[i]) } } return res } console.log(unique(array)); // [ '1', 1, '2', 2 ]
既然不使用數(shù)組自帶的API方法,那我們首先考慮的就是用雙重for循環(huán)了,如上述代碼:
- 我們準(zhǔn)備了一個(gè)空的結(jié)果數(shù)組
- 我們對(duì)需要去重的數(shù)組進(jìn)行循環(huán)
- 在第一層數(shù)據(jù)中再套一層循環(huán),根據(jù)下標(biāo)判斷結(jié)果數(shù)組內(nèi)是否有重復(fù)項(xiàng)。
我們調(diào)用該方法,打印結(jié)構(gòu)如上述代碼的注解處,成功的實(shí)現(xiàn)了對(duì)數(shù)組的去重。
2. 使用 indexOf
既然有不使用數(shù)組API的,那就肯定有使用數(shù)組API的,下面看我使用indexOf完成數(shù)組的去重,代碼如下:
var array = ['1', 1, '1', '1', '2', 2] function unique(array) { let res = [] for (let i = 0; i < array.length; i++) { if (res.indexOf(array[i]) === -1) { // 返回找到的第一個(gè)值得下標(biāo) res.push(array[i]) } } return res } console.log(unique(array))// [ '1', 1, '2', 2 ]
如上述代碼, 我們巧妙了使用了indexOf查找結(jié)果數(shù)組中是否已經(jīng)存在,如果不存在才向結(jié)果數(shù)組中添加,實(shí)現(xiàn)了數(shù)組去重。
在上述代碼的基礎(chǔ)上,我們還可以轉(zhuǎn)變一下,將for循環(huán)內(nèi)的語(yǔ)句改為:
if (array.indexOf((array[i])) == array.lastIndexOf(array[i])) { i++ } else { array.splice(array.lastIndexOf(array[i]), 1) }
不新增其他變量,直接通過(guò)indexOf和lastIndexOf判斷該值是否在原數(shù)組內(nèi)為唯一值,從而直接修改原數(shù)組,實(shí)現(xiàn)數(shù)組的去重。
3. 使用 sort
對(duì)于數(shù)組去重,我們除了通過(guò)下標(biāo)找出是否有重復(fù)項(xiàng)之外,我們還可以先排序,然后在判斷前后項(xiàng)是否相同來(lái)實(shí)現(xiàn)去重,代碼如下:
var ?array = [1, 3, 5, 4, 2, 1, 2, 4, 4, 4] function unique(array) { let res = [] let sortedArray = array.concat().sort() //concat() 返回新的數(shù)組 let seen; for (let i = 0; i < sortedArray.length; i++) { if (!i || seen !== sortedArray[i]) { res.push(sortedArray[i]) } seen = sortedArray[i] } return res } console.log(unique(array)); // [ 1, 2, 3, 4, 5 ]
如上述代碼, 我們先獲取一個(gè)排好序的新數(shù)組,再對(duì)新數(shù)組進(jìn)行循環(huán),判斷保存前一個(gè)值的seen與當(dāng)前值是否相同來(lái)實(shí)現(xiàn)數(shù)組去重。
溫馨小提示: 由于數(shù)組的排序方法不能區(qū)分?jǐn)?shù)組和字符串,所以想要使用此方法必須要保證數(shù)組的值的類型相同,不然會(huì)出bug
4. 使用 filter
既然都用到了sort排序了,那我直接抬出ES6數(shù)組新增的filter過(guò)濾器API也不過(guò)分吧,代碼如下:
var array = ['1', 1, '1', '1', '2', 2] function unique(array) { let res = array.filter((item, index, array) => { return array.indexOf(item) === index }) return res } console.log(unique(array)); // [ '1', 1, '2', 2 ]
如上述代碼,filter直接使用array.indexOf(item) === index
作為過(guò)濾條件返回出一個(gè)新的數(shù)組,實(shí)現(xiàn)數(shù)組去重。
如上述代碼,我們結(jié)合了 indexOf方法作為過(guò)濾條件,那我們也可以結(jié)合一下sort方法吧,直接使用一行代碼就解決了數(shù)組的去重。代碼如下:
function unique(array) { return array.concat().sort().filter((item, index, array) => !index || item !== array[item - 1]) } console.log(unique(array)); // [ '1', 1, '2', 2 ]
5. 使用Set、Map、或者對(duì)象
除了上述的通過(guò)數(shù)組API和不使用數(shù)組API的方法外,我們還能想到的就是借助對(duì)象來(lái)實(shí)現(xiàn)數(shù)組的去重。使用Set數(shù)據(jù)結(jié)構(gòu)是我們最容易想到的辦法,使用Map與對(duì)象方法的相似,都是以數(shù)組的值作為key,再將所有的可以取出來(lái)組成一個(gè)數(shù)組。 我就不給小伙伴們演示代碼了,感興趣的小伙伴可以自己動(dòng)手試試。
(對(duì)于對(duì)象的key只能為字符串這個(gè)問(wèn)題,我們可以換個(gè)思路,將下標(biāo)存為key,值存為value,判斷不同key的值相不相同來(lái)實(shí)現(xiàn)數(shù)組去重。我們還可以在存key時(shí)加上其類型,然后進(jìn)行一次轉(zhuǎn)換。)
自己封裝一個(gè)去重API
在介紹上述數(shù)組去重的方法后,我們?cè)賮?lái)總結(jié)一下,將其融合成一個(gè)有復(fù)用性,而且還可以適用不同情況的API方法。
我來(lái)介紹一下如下我封裝的一個(gè)數(shù)組去重的API方法,
- 該方法可接受三個(gè)參數(shù),第一個(gè)參數(shù)為需要去重的數(shù)組,第二個(gè)參數(shù)為該數(shù)組是否為排好序的數(shù)組,第三個(gè)參數(shù)為一個(gè)回調(diào)函數(shù)
- 該回調(diào)函數(shù)也有三個(gè)參數(shù),分別為值,下標(biāo),需要去重?cái)?shù)組。該回調(diào)函數(shù)的作用是方便用戶對(duì)數(shù)組進(jìn)行一些額外的處理(例如將大寫轉(zhuǎn)為小寫)
- 第二,三參數(shù)可不傳遞。
var array = [1, 2, '1', 'a', 'A', 2, 1] var array2 = [1, 1, '1', 2, 2] function uniq(array, isSorted, iteratee) { let seen = [] let res = [] for(let i = 0; i < array.length; i++){ let computed = iteratee ? iteratee(array[i], i,array) : array[i] if(isSorted) { if(!i || seen !== array[i]){ res.push(array[i]) } seen = array[i] }else if(iteratee) { if(seen.indexOf(computed) === -1){ seen.push(computed) res.push(computed) } } else { if(res.indexOf(array[i]) === -1) { res.push(array[i]) } } } return res } let result = uniq(array, false, function(item, index, arr){ return typeof item == 'string' ? item.toLowerCase() : item }) console.log(result); // [ 1, 2, '1', 'a' ] console.log(uniq(array2, true)); // [ 1, 2 ]
總結(jié)
對(duì)于數(shù)組的去重,當(dāng)我們能在面試中說(shuō)到這個(gè)多方法的話,這道面試題也就過(guò)了,雖然這道面試不難,但如果我們想要想到這個(gè)多方法的話,還是需要許多知識(shí)儲(chǔ)備的。
以上就是JavaScript中數(shù)組去重的辦法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript數(shù)組去重的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
從數(shù)組中隨機(jī)取x條不重復(fù)數(shù)據(jù)的JS代碼
這篇文章主要介紹了從數(shù)組中隨機(jī)取x條不重復(fù)數(shù)據(jù)的JS代碼,有需要的朋友可以參考一下2013-12-12JavaScript Generator函數(shù)使用分析
生成器Generator是JavaScript ES6引入的特性,它讓我們可以分段執(zhí)行一個(gè)函數(shù)。但是在談?wù)撋善鳎℅enerator)之前,我們要先了解迭代器Iterator2022-10-10JavaScript中數(shù)組去重的辦法總結(jié)
你是否在面試的過(guò)程中被考到過(guò)給你一個(gè)數(shù)組讓你去掉重復(fù)項(xiàng)呢,下面小編就來(lái)總結(jié)一下對(duì)于數(shù)組去重這道簡(jiǎn)單的面試題時(shí),我們可以回答的方法有什么吧2023-06-06antd項(xiàng)目實(shí)現(xiàn)彩蛋效果的詳細(xì)代碼
這篇文章主要介紹了antd項(xiàng)目如何實(shí)現(xiàn)彩蛋效果,首先在components目錄下創(chuàng)建Transform目錄,包括index.css、index.js,index.js是主要的邏輯代碼,下面對(duì)代碼進(jìn)行分析,需要的朋友可以參考下2022-09-09js實(shí)現(xiàn)當(dāng)復(fù)選框選擇匿名登錄時(shí)隱藏登錄框效果
這篇文章主要介紹了js實(shí)現(xiàn)當(dāng)復(fù)選框選擇匿名登錄時(shí)隱藏登錄框效果,實(shí)例分析了javascript動(dòng)態(tài)操作頁(yè)面元素樣式的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-08-08