JavaScript數(shù)組去重的五種方法及其他細節(jié)和拓展
前言
您或許會疑惑,網(wǎng)上那么多去重方法,這篇文章還有什么意義?
別著急,這篇文章只節(jié)選了簡單的,好玩的,古老的,有實際講解意義的去重方法,除了去重的實現(xiàn)以外,我還將和您分享這其中的其他細節(jié)和拓展。
您或許不理解,為什么只有五種?
當然,我可以舉例出更多的例子來,但那有什么意義呢?工作中用不到那么多,會其中一二就可以。即使是面試,能說出五種也是完全足夠的。所以,我們完全沒有必要去記憶更多的去重方式。
五種方式
最簡單的方法,ES6的Set去重(最推薦)
這個方法是我日常開發(fā)中最喜歡用的方法,因為,他的使用方法是所有去重中最簡單的。而我是一個懶癌患者。
new Set是ES6新推出的一種類型。他和數(shù)組的區(qū)別在于,Set類型中的數(shù)據(jù)不可以有重復的值。當然,數(shù)組的一些方法Set也無法調(diào)用。
使用方法:其實很簡單,將一個數(shù)組轉(zhuǎn)化為Set數(shù)據(jù),再轉(zhuǎn)化回來,就完成了去重。
const arr = [1,1,2,2,3,3,4,4,5,5]; const setData = Array.from(new Set(arr)); console.log(setData);
圖例↓
但是Set去重有一個弊端,他無法去重引用類型的數(shù)據(jù)。比如對象數(shù)組。
圖例:
所以如果您的數(shù)組中都是值類型的數(shù)據(jù)(比如全string或者全number),那么使用Set進行去重一定是首選,會為您減少很多的麻煩。
最古老的方法,雙重for循環(huán)去重
在很早以前,還沒有Set,沒有map,filter的時候,雙重for循環(huán)幾乎是去重的唯一方式。
//雙重循環(huán)去重 const handleRemoveRepeat = (arr) => { for (let i=0,len = arr.length; i < len; i++) { for (let j = i + 1; j < len; j++) { if (arr[i] === arr[j]) { arr.splice(j, 1); j--; len--; } } } return arr; };
圖例:
這里有一個有意思的地方,或許您不太明白,為什么我的for循環(huán)的初始表達式中聲明了兩個東西:let i = 0;len = arr.length;
我來給您解答:
被圈起來的三個表示的是for循環(huán)的三個表達式,依次分別是:初始表達式,判斷表達式,自增表達式。其中,初始表達式在for循環(huán)開始的時候會執(zhí)行一次,以后就不會再執(zhí)行了,但是判斷表達式和自增表達式會在每一次循環(huán)的時候都去執(zhí)行。
如果您不太理解文字表達,沒關(guān)系,我畫了張圖。
您或許已經(jīng)發(fā)現(xiàn),后一個圈中的內(nèi)容會陷入一個循環(huán)。
但這和我們一開始len = arr.length有什么關(guān)系呢?
值得注意的是,如果一開始定義,那么每一次循環(huán),都需要走 arr.length,length可是個方法,雖然他的消耗并不大,但在for循環(huán)中這個消耗會被方法,假設這個循環(huán)需要循環(huán)10000次呢,length就會被執(zhí)行10000次。
最雞肋的去重方式,indexOf去重
indexOf還是相對簡單又雞肋。為什么說他雞肋呢?說難吧,indexOf方法確實比上文的雙重for循環(huán)簡單。說簡單吧,嘿,他沒Set方法去重來的更簡單。所以雞肋。
//去重 const handleRemoveRepeat = (arr) => { let repeatArr = []; for (let i = 0,len = arr.length ; i < len; i++) if (repeatArr.indexOf(arr[i]) === -1) repeatArr.push(arr[i]) return repeatArr; }
圖例:
同樣的,這個方法也有一個細節(jié)點,您或許已經(jīng)發(fā)現(xiàn)了,上文的if和for沒有花括號;是的;for和if都默認對下面一條語句負責。在沒有必要的情況下,不用多加一個{}。
或許您會覺得這不可讀,這就是有意思的地方了,這是一個工具類方法,注定被藏在utils中的一個方法,他無關(guān)業(yè)務邏輯,并不需要有太大可讀性。
而且,這么寫還有一個很原因:給人的視覺沖擊會比較大。說點人話就是 -----很裝;
一種類似于indexOf的去重方法,includes去重
使用includes的去重方法和indexOf不能說很像,基本上一模一樣。變換的僅僅只是判斷方法。
includes的判斷方法更簡單了。循環(huán)數(shù)組的每一樣,用新數(shù)組檢測當前數(shù)組中是否包含數(shù)組項,如果不包含,則追加該元素
const handleRemoveRepeat = (arr) => { let repeatArr = []; for (let i = 0,len = arr.length ; i < len; i++) if (!repeatArr.includes(arr[i])) repeatArr.push(arr[i]) return repeatArr; }
圖例
includes方法在除了去重以外的場景,還是很好用的。
最有趣的去重方法,使用filter去重。
使用filter配合indexOf進行的去重過程,真的可以非常的簡單且富含趣味性。
//去重 const handleRemoveRepeat = (arr) => arr.filter((item,index) => arr.indexOf(item,0) === index);
是的,沒了,就一行。
圖例
您是否沒有反應過來?乍一看,不知道他是怎么完成去重的。
小問題,我為您解答疑惑。
indexOf的特性是返回被查找的目標中包含的第一個位置的索引
如圖,下標為0和下標為4的位置存儲的都是“1”。但是indexOf()只返回了0。因為indexOf的特性是返回被查找的目標中包含的第一個位置的索引。
同樣的,我們可以利用這個特性。來完成去重,文字描述恐怕很難表達準確,您可以看看下面的這張圖。
您或許會問:如果要去重對象數(shù)組怎么辦?
去除對象數(shù)組的方式他并不是很穩(wěn)定,這不像我們?nèi)ブ刂殿愋蛿?shù)據(jù)的數(shù)組,上面的五種方法隨便復制一種,往里面一調(diào)用就好了。絕對不會出問題。
但是對象數(shù)組去重,需要有一個去重條件,也就是根據(jù)哪個字段進行去重。
用雙重循環(huán)去重舉個例子:
圖例
如上圖,我們就是拿數(shù)據(jù)的id作為去重條件的。
像這樣的對象數(shù)組就不能直接提供方法,因為每一個場景下的對象數(shù)組都不一定一樣。我這是根據(jù)id去重,萬一其他地方需要根據(jù)其他字段去重呢。
所以,如果您需要去重對象,根據(jù)上方的截圖中的代碼。使用雙重for循環(huán)的方法,自己自定義一個可以滿足您當前業(yè)務需求的去重方法。
總結(jié)
到此這篇關(guān)于JavaScript數(shù)組去重的五種方法及其他細節(jié)和拓展的文章就介紹到這了,更多相關(guān)js數(shù)組去重方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序錄音實現(xiàn)功能并上傳(使用node解析接收)
在我們的日常開發(fā)中經(jīng)常會遇到錄音功能,并上傳到服務器,今天小編給大家分享微信小程序錄音功能實現(xiàn)并上傳錄音文件,使用node解析接收,需要的朋友可以參考下2020-02-02js數(shù)組高階函數(shù)之includes()方法總結(jié)
JS的數(shù)組是一種特殊的對象,其特點是在值的列表中按照順序存放值,在 JS中,數(shù)組是由中括號 [] 括起來的數(shù)值序列,本篇文章給大家介紹js數(shù)組高階函數(shù)——includes()方法,感興趣的朋友一起看看吧2023-12-12JavaScript中函數(shù)的四種調(diào)用方式總結(jié)
這篇文章主要為大家詳細介紹了JavaScript中函數(shù)的四種調(diào)用方式,文中的示例代碼講解詳細,對我們深入掌握JavaScript有一定的幫助,需要的可以參考下2023-10-10ion content 滾動到底部會遮住一部分視圖的快速解決方法
本文給大家?guī)砹薸on content 滾動到底部會遮住一部分視圖的快速解決方法,其實解決方法超簡單的,只要在你的controller里面預先注入$ionicScrollDelegate就可以了,感興趣的朋友通過本文一起學習吧2016-09-09