關(guān)于JavaScript數(shù)組去重的一些理解匯總
前言
做前端開發(fā)幾年,在項(xiàng)目中用到數(shù)組去重的機(jī)會(huì)倒不是很多,但是在面試的時(shí)候卻經(jīng)常被問到,個(gè)人理解,這道題真正考的是對(duì)JavaScript的基礎(chǔ)的掌握,因?yàn)橛泻芏喾N方式可以做到。這次就根據(jù)這道題,將相關(guān)的知識(shí)理解透徹。
一、ES6中的new Set方式
先看看MDN上對(duì)Set的描述:
Set 對(duì)象允許你存儲(chǔ)任何類型的唯一值,無論是原始值或者是對(duì)象引用。
Set對(duì)象是值的集合,你可以按照插入的順序迭代它的元素。 Set中的元素只會(huì)出現(xiàn)一次,即 Set 中的元素是唯一的。
關(guān)鍵字:任何類型都可以存儲(chǔ)、存儲(chǔ)進(jìn)來的值都是唯一的,這樣就可以做到先把數(shù)組中重復(fù)的數(shù)據(jù)去掉。
const list1 = [1, 2, 3, 7, 11, 56, 3, 2, 4, 5] const list2 = new Set(list1) console.log(list2)
看一下返回的結(jié)果:
由結(jié)果可知,返回了一個(gè)可迭代的Set對(duì)象,此時(shí)還需要把Set對(duì)象轉(zhuǎn)為數(shù)組。此時(shí)可以用到
Array.from()。
**Array.from()** 方法從一個(gè)類似數(shù)組或可迭代對(duì)象創(chuàng)建一個(gè)新的,淺拷貝的數(shù)組實(shí)例.
剛好new Set()返回的就是一個(gè)可迭代的對(duì)象。
const list3 = Array.from(new Set([null, null, undefined, 12, undefined, 7, 2, 1, 22, 2, function a(){}, function a(){}, {}, {}]))
結(jié)果是返回了一個(gè)數(shù)組:
這種方式不考慮兼容性,且去不掉重復(fù)的function和{}
關(guān)于Array.from()的擴(kuò)展
Array.from(arrayLike[, mapFn[, thisArg]])
arrayLike: 偽數(shù)組和可迭代對(duì)象
mapFn:每個(gè)元素會(huì)執(zhí)行這個(gè)回調(diào)方法
thisArg: 執(zhí)行回調(diào)函數(shù)時(shí)this的指向。
const list4 = Array.from('name', arg => arg + 12) console.log(list4) // [ 'n12', 'a12', 'm12', 'e12' ]
偽數(shù)組對(duì)象(擁有一個(gè) length 屬性和若干索引屬性的任意對(duì)象, 如string)
可迭代對(duì)象(可以獲取對(duì)象中的元素,如 Map和 Set 等)
二、set的另一種寫法
const list20 = [5, 3, 5, 5, 6, 37, 22, 22] console.log([...new Set(list20)])
其實(shí)跟第一種差不多
三、嵌套的for循環(huán)
const list5 = [null, null, undefined, undefined, {}, {}, function q() {}, function q() {}, 34, 2, 1, 2] for(let i = 0; i < list3.length; i++) { for (let j = i + 1; j < list3.length; j++) { if (list3[i] === list3[j]) { list3.splice(j, 1) // 將重復(fù)的數(shù)據(jù)刪掉一個(gè) j-- // 因?yàn)閯h除掉了一個(gè)元素,就從這個(gè)元素的索引重新開始 } } }
這種方式用了splice(index, num)的方法,返回的結(jié)果也沒有把function和對(duì)象給去掉。我們能想到的最簡(jiǎn)單的方式就是這種去重方式。
四、indexOf方式
const list6 = [null, null, undefined, undefined, NaN, NaN, false, 'false', function a(){}, function a() {}, {}, {}] const list7 = [] for(let k = 0; k<list6.length; k++) { if (list7.indexOf(list6[k]) === -1) { list7.push(list6[k]) } } console.log(list7, 'list7') // [null, undefined,NaN, NaN,false,'false',[Function: a], [Function: a],{},{}] list7
關(guān)于indexOf
Array構(gòu)造函數(shù)和String構(gòu)造函數(shù)的原型上都有這個(gè)方法
MDN上對(duì)他們的解釋分別是:
**indexOf()**方法返回在數(shù)組中可以找到一個(gè)給定元素的第一個(gè)索引,如果不存在,則返回-1。
arr.indexOf(searchElement[, fromIndex])
**indexOf()** 方法返回調(diào)用它的 String 對(duì)象中第一次出現(xiàn)的指定值的索引,從 fromIndex 處進(jìn)行搜索。如果未找到該值,則返回 -1。
str.indexOf(searchValue [, fromIndex])
這么一看 就知道他倆用法一樣。
五、sort
先看看關(guān)于sort的解釋:
**sort()** 方法用原地算法對(duì)數(shù)組的元素進(jìn)行排序,并返回?cái)?shù)組。默認(rèn)排序順序是在將元素轉(zhuǎn)換為字符串,然后比較它們的UTF-16代碼單元值序列時(shí)構(gòu)建的
由于它取決于具體實(shí)現(xiàn),因此無法保證排序的時(shí)間和空間復(fù)雜性。
所以這種方式,在數(shù)組長(zhǎng)的時(shí)候可能保證不了性能。用它去重的思路是什么呢?先用sort排序,然后前一個(gè)跟后一個(gè)比較,這樣相同的值永遠(yuǎn)都是鄰關(guān)系。
const list8 = [null, null, undefined, undefined, NaN, NaN, false, 'false', function a(){}, function a() {}, {}, {}] const list9 = list8.sort() const list10 = [list9[0]] for(let i = 1; i<list9.length; i++) { if (list9[i] !== list9[i-1]) { list10.push(list9[i]) } }
這一看就很容易理解。
六、includes
const list11 = [null, null, undefined, undefined, NaN, NaN, false, 'false', function a(){}, function a() {}, {}, {}] const list12 = [] for (let i = 0; i<list11.length ; i++) { if (!list12.includes(list11[i])) { list12.push(list11[i]) } }
此結(jié)果沒有把function和{}去重,其他的都去重了。
includes也是Array構(gòu)造函數(shù)和String構(gòu)造函數(shù)上都有的方法。
七、filter和indexOf
// 數(shù)組去重方式6-filter和indexOf const list13 = [1, 2, 3, 3, 5] const list14 = list13.filter((item, index, arr) => { // 也就是在遍歷這個(gè)數(shù)組list13的時(shí)候,每次拿當(dāng)前的元素跟此數(shù)組中這個(gè)元素第一次出現(xiàn)的位置相比,如果位置是一致的,就返回當(dāng)前元素 return list13.indexOf(item, 0) === index })
八、遞歸
const list15 = [1, 2, 3, 4, 5, 7, 6, 4, 3] const list16 = list15 const len = list16.length list16.sort(function(a, b) { return a - b }) // 先排序 function loop(index) { if (index >= 1) { if (list16[index] === list16[index - 1]) { list16.splice(index, 1) } loop(index - 1) } } loop(len - 1)
關(guān)于sort排序
在排序的時(shí)候 我們可能忽略了一個(gè)問題,可能得到的并不是我們想要的結(jié)果,比如下面的例子:
const list17 = [22, 1, 2, 15, 3, 4, 3, 1, 11] console.log(list17.sort()) // [1, 1, 11, 15, 2, 22, 3, 3, 4]
看看得到的結(jié)果,根本就不是按照從小到大排的。這是因?yàn)椋耗J(rèn)排序順序是在將元素轉(zhuǎn)換為字符串,然后比較它們的UTF-16代碼單元值序列時(shí)構(gòu)建的。
所以 要另找一種排序的方法,就是給sort傳入一個(gè)函數(shù)。
arr.sort([compareFunction])
參數(shù):
- compareFunction: 可傳可不傳,傳的話用來指定按某種順序進(jìn)行排列的函數(shù)。如果省略,元素按照轉(zhuǎn)換為的字符串的各個(gè)字符的Unicode位點(diǎn)進(jìn)行排序。
- compareFunction的參數(shù)1-firstEl: 用于比較的第一個(gè)元素
- compareFunction的參數(shù)2-secondEl: 用于比較的第二個(gè)元素
- 如果 compareFunction(a, b) 小于 0 ,那么 a 會(huì)被排列到 b 之前;
- 如果 compareFunction(a, b) 等于 0 , a 和 b 的相對(duì)位置不變。備注: ECMAScript 標(biāo)準(zhǔn)并不保證這一行為,而且也不是所有瀏覽器都會(huì)遵守(例如 Mozilla 在 2003 年之前的版本);
- 如果 compareFunction(a, b) 大于 0 , b 會(huì)被排列到 a 之前。
- compareFunction(a, b) 必須總是對(duì)相同的輸入返回相同的比較結(jié)果,否則排序的結(jié)果將是不確定的。
返回值:
返回的是已經(jīng)原地排序的數(shù)組。
九、用Map數(shù)據(jù)結(jié)構(gòu)排序
const list 18 = [2, 3, 33, 2, 5, 1, 3] const map1 = new Map() for(let i = 0; i<list18.length; i++) { if (map1.get(list18[i])) { map1.set(list18[i], true) } else { map1.set(list18[i], false) list19.push(list18[i]) } }
這個(gè)比較好理解, 就不多說了。
總結(jié)
到此這篇關(guān)于關(guān)于JavaScript數(shù)組去重的一些理解的文章就介紹到這了,更多相關(guān)JavaScript數(shù)組去重內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js實(shí)現(xiàn)圖片淡入淡出切換簡(jiǎn)易效果
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)圖片淡入淡出切換簡(jiǎn)易效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08javascript 原型與原型鏈的理解及實(shí)例分析
這篇文章主要介紹了javascript 原型與原型鏈的理解,結(jié)合實(shí)例形式分析了javascript 原型與原型鏈的原理、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-11-11跟我學(xué)習(xí)javascript的浮點(diǎn)數(shù)精度
跟我學(xué)習(xí)javascript的浮點(diǎn)數(shù)精度,帶大家真正的理解JavaScript的浮點(diǎn)數(shù),提醒大家當(dāng)心浮點(diǎn)運(yùn)算中的精度陷阱,需要的朋友可以參考下2015-11-11JavaScript判斷瀏覽器和hack滾動(dòng)條的寫法
這篇文章主要介紹了JavaScript判斷瀏覽器和hack滾動(dòng)條的寫法,需要的朋友可以參考下2017-07-07JavaScript實(shí)現(xiàn)彩虹文字效果的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)彩虹文字效果的方法,涉及javascript操作文字樣式的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04跟我學(xué)Nodejs(一)--- Node.js簡(jiǎn)介及安裝開發(fā)環(huán)境
這篇文章主要介紹了Node.js簡(jiǎn)介及安裝開發(fā)環(huán)境,需要的朋友可以參考下2014-05-05