js數(shù)組去重的常用方法總結(jié)
JS實(shí)現(xiàn)數(shù)組去重(重復(fù)的元素只保留一個(gè))
1、遍歷數(shù)組法
1.遍歷數(shù)組法
它是最簡(jiǎn)單的數(shù)組去重方法(indexOf方法)
實(shí)現(xiàn)思路:新建一個(gè)數(shù)組,遍歷去要重的數(shù)組,當(dāng)值不在新數(shù)組的時(shí)候(indexOf為-1)就加入該新數(shù)組中;
例子1
function unique(arr) { if (!Array.isArray(arr)) { console.log('type error!') return } var array = []; for (var i = 0; i < arr.length; i++) { if (array .indexOf(arr[i]) === -1) { array .push(arr[i]) } } return array; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}沒(méi)有去重
例子2
var arr=[2,8,5,0,5,2,6,7,2]; function unique1(arr){ var hash=[]; for (var i = 0; i < arr.length; i++) { if(hash.indexOf(arr[i])==-1){ hash.push(arr[i]); } } return hash; }
2.數(shù)組下標(biāo)判斷法
調(diào)用indexOf方法,性能和方法1差不多
實(shí)現(xiàn)思路:如果當(dāng)前數(shù)組的第 i 項(xiàng)在當(dāng)前數(shù)組中第一次出現(xiàn)的位置不是 i,那么表示第 i 項(xiàng)是重復(fù)的,忽略掉。否則存入結(jié)果數(shù)組。
function unique2(arr){ var hash=[]; for (var i = 0; i < arr.length; i++) { if(arr.indexOf(arr[i])==i){ hash.push(arr[i]); } } return hash; }
3.排序后相鄰去除法
實(shí)現(xiàn)思路:給傳入的數(shù)組排序,排序后相同的值會(huì)相鄰,然后遍歷排序后數(shù)組時(shí),新數(shù)組只加入不與前一值重復(fù)的值。
function unique3(arr){ arr.sort(); var hash=[arr[0]]; for (var i = 1; i < arr.length; i++) { if(arr[i]!=hash[hash.length-1]){ hash.push(arr[i]); } } return hash; }
4.優(yōu)化遍歷數(shù)組法(不推薦)
實(shí)現(xiàn)思路:雙層循環(huán),外循環(huán)表示從0到arr.length,內(nèi)循環(huán)表示從i+1到arr.length
將沒(méi)重復(fù)的右邊值放入新數(shù)組。(檢測(cè)到有重復(fù)值時(shí)終止當(dāng)前循環(huán)同時(shí)進(jìn)入外層循環(huán)的下一輪判斷)
function unique4(arr){ var hash=[]; for (var i = 0; i < arr.length; i++) { for (var j = i+1; j < arr.length; j++) { if(arr[i]===arr[j]){ ++i; } } hash.push(arr[i]); } return hash; }
上面遍歷經(jīng)過(guò)測(cè)試后有bug,并不能完全去重
因?yàn)檫@次我做的是對(duì)js對(duì)象元素去重,我在參考時(shí)發(fā)現(xiàn)此bug,如果時(shí)數(shù)組去重,建議用第一種方法。
quan_lst 里面是一個(gè)一個(gè)的js字面量對(duì)象,根據(jù)json里面的屬性進(jìn)行判定去重
function unique(quan_lst){ //去掉重復(fù)選取的數(shù)據(jù) for (var i = 0; i < quan_lst.length; i++) { for (var j =i+1; j <quan_lst.length; ) { if (quan_lst[i].photoid == quan_lst[j].photoid ) {//通過(guò)photoid屬性進(jìn)行匹配; quan_lst.splice(j, 1);//去除重復(fù)的對(duì)象; }else { j++; } } } }
5.ES6實(shí)現(xiàn)
基本思路:ES6提供了新的數(shù)據(jù)結(jié)構(gòu)Set。它類似于數(shù)組,但是成員的值都是唯一的,沒(méi)有重復(fù)的值。
Set函數(shù)可以接受一個(gè)數(shù)組(或類似數(shù)組的對(duì)象)作為參數(shù),用來(lái)初始化。
function unique5(arr){ var x = new Set(arr); return [...x]; }
利用ES6 Set去重(ES6中最常用)
function unique (arr) { return Array.from(new Set(arr)) } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
擴(kuò)展:如果重復(fù),則去掉該元素
數(shù)組下標(biāo)去重
function unique22(arr){ var hash=[]; for (var i = 0; i < arr.length; i++) { if(arr.indexOf(arr[i])==arr.lastIndexOf(arr[i])){ hash.push(arr[i]); } } return hash; }
補(bǔ)充:原先自己一直以為indexOf是針對(duì)字符串,原來(lái)indexOf也可以查詢出數(shù)組元素所在的數(shù)組中的位置(以0開(kāi)始計(jì)算),
以上轉(zhuǎn)自于軒悅的博客,學(xué)了很多思路。
6、利用sort()
利用sort()排序方法,然后根據(jù)排序后的結(jié)果進(jìn)行遍歷及相鄰元素比對(duì)。
function unique(arr) { if (!Array.isArray(arr)) { console.log('type error!') return; } arr = arr.sort() var arrry= [arr[0]]; for (var i = 1; i < arr.length; i++) { if (arr[i] !== arr[i-1]) { arrry.push(arr[i]); } } return arrry; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) // [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined] //NaN、{}沒(méi)有去重
7、利用includes
includes 檢測(cè)數(shù)組是否有某個(gè)值
function unique(arr) { if (!Array.isArray(arr)) { console.log('type error!') return } var array =[]; for(var i = 0; i < arr.length; i++) { if( !array.includes( arr[i]) ) {//includes 檢測(cè)數(shù)組是否有某個(gè)值 array.push(arr[i]); } } return array } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}] //{}沒(méi)有去重
八、利用for嵌套for,然后splice去重(ES5中最常用)推薦
雙層循環(huán),外層循環(huán)元素,內(nèi)層循環(huán)時(shí)比較值。值相同時(shí),則刪去這個(gè)值。
function unique(arr){ for(var i=0; i<arr.length; i++){ for(var j=i+1; j<arr.length; j++){ if(arr[i]==arr[j]){ //第一個(gè)等同于第二個(gè),splice方法刪除第二個(gè) arr.splice(j,1); j--; } } } return arr; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}] //NaN和{}沒(méi)有去重,兩個(gè)null直接消失了
9、利用對(duì)象的屬性不能相同的特點(diǎn)進(jìn)行去重(這種數(shù)組去重的方法有問(wèn)題,不建議用,有待改進(jìn))
function unique(arr) { if (!Array.isArray(arr)) { console.log('type error!') return } var arrry= []; var obj = {}; for (var i = 0; i < arr.length; i++) { if (!obj[arr[i]]) { arrry.push(arr[i]) obj[arr[i]] = 1 } else { obj[arr[i]]++ } } return arrry; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", 15, false, undefined, null, NaN, 0, "a", {…}] //兩個(gè)true直接去掉了,NaN和{}去重
十、利用hasOwnProperty
利用hasOwnProperty 判斷是否存在對(duì)象屬性
function unique(arr) { var obj = {}; return arr.filter(function(item, index, arr){ return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true) }) } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}] //所有的都去重了
十一、利用filter
function unique(arr) { return arr.filter(function(item, index, arr) { //當(dāng)前元素,在原始數(shù)組中的第一個(gè)索引==當(dāng)前索引值,否則返回當(dāng)前元素 return arr.indexOf(item, 0) === index; }); } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
十二、利用遞歸去重
function unique(arr) { var array= arr; var len = array.length; array.sort(function(a,b){ //排序后更加方便去重 return a - b; }) function loop(index){ if(index >= 1){ if(array[index] === array[index-1]){ array.splice(index,1); } loop(index - 1); //遞歸loop,然后數(shù)組去重 } } loop(len-1); return array; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]
十三、利用Map數(shù)據(jù)結(jié)構(gòu)去重
創(chuàng)建一個(gè)空Map數(shù)據(jù)結(jié)構(gòu),遍歷需要去重的數(shù)組,把數(shù)組的每一個(gè)元素作為key存到Map中。由于Map中不會(huì)出現(xiàn)相同的key值,所以最終得到的就是去重后的結(jié)果。
function unique(arr){ return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]); } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)); // [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
十四、利用reduce+includes
function unique(arr){ return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]); } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)); // [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
十五、[...new Set(arr)]
[...new Set(arr)] //代碼就是這么少----(其實(shí),嚴(yán)格來(lái)說(shuō)并不算是一種,相對(duì)于第一種方法來(lái)說(shuō)只是簡(jiǎn)化了代碼)
PS:有些文章提到了foreach+indexOf數(shù)組去重的方法,個(gè)人覺(jué)得都是大同小異,所以沒(méi)有寫(xiě)上去。
下面是其他網(wǎng)友的補(bǔ)充
第一種是比較常規(guī)的方法
思路:
1.構(gòu)建一個(gè)新的數(shù)組存放結(jié)果
2.for循環(huán)中每次從原數(shù)組中取出一個(gè)元素,用這個(gè)元素循環(huán)與結(jié)果數(shù)組對(duì)比
3.若結(jié)果數(shù)組中沒(méi)有該元素,則存到結(jié)果數(shù)組中
Array.prototype.unique1 = function(){ var res = [this[0]]; for(var i = 1; i < this.length; i++){ var repeat = false; for(var j = 0; j < res.length; j++){ if(this[i] == res[j]){ repeat = true; break; } } if(!repeat){ res.push(this[i]); } } return res; } var arr = [1, 'a', 'a', 'b', 'd', 'e', 'e', 1, 0] alert(arr.unique1());
第二種方法比上面的方法效率要高
思路:
1.先將原數(shù)組進(jìn)行排序
2.檢查原數(shù)組中的第i個(gè)元素 與 結(jié)果數(shù)組中的最后一個(gè)元素是否相同,因?yàn)橐呀?jīng)排序,所以重復(fù)元素會(huì)在相鄰位置
3.如果不相同,則將該元素存入結(jié)果數(shù)組中
Array.prototype.unique2 = function(){ this.sort(); //先排序 var res = [this[0]]; for(var i = 1; i < this.length; i++){ if(this[i] !== res[res.length - 1]){ res.push(this[i]); } } return res; } var arr = [1, 'a', 'a', 'b', 'd', 'e', 'e', 1, 0] alert(arr.unique2());
第二種方法也會(huì)有一定的局限性,因?yàn)樵谌ブ厍斑M(jìn)行了排序,所以最后返回的去重結(jié)果也是排序后的。如果要求不改變數(shù)組的順序去重,那這種方法便不可取了。
第三種方法(推薦使用)
思路:
1.創(chuàng)建一個(gè)新的數(shù)組存放結(jié)果
2.創(chuàng)建一個(gè)空對(duì)象
3.for循環(huán)時(shí),每次取出一個(gè)元素與對(duì)象進(jìn)行對(duì)比,如果這個(gè)元素不重復(fù),則把它存放到結(jié)果數(shù)組中,同時(shí)把這個(gè)元素的內(nèi)容作為對(duì)象的一個(gè)屬性,并賦值為1,存入到第2步建立的對(duì)象中。
說(shuō)明:至于如何對(duì)比,就是每次從原數(shù)組中取出一個(gè)元素,然后到對(duì)象中去訪問(wèn)這個(gè)屬性,如果能訪問(wèn)到值,則說(shuō)明重復(fù)。
Array.prototype.unique3 = function(){ var res = []; var json = {}; for(var i = 0; i < this.length; i++){ if(!json[this[i]]){ res.push(this[i]); json[this[i]] = 1; } } return res; } var arr = [112,112,34,'你好',112,112,34,'你好','str','str1']; alert(arr.unique3());
以上就是js數(shù)組去重的三種常用方法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于js數(shù)組去重的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
硬盤(pán)瀏覽程序,保存成網(wǎng)頁(yè)格式便可使用
硬盤(pán)瀏覽程序,保存成網(wǎng)頁(yè)格式便可使用...2006-12-12微信小程序module.exports模塊化操作實(shí)例淺析
這篇文章主要介紹了微信小程序module.exports模塊化操作,結(jié)合實(shí)例形式簡(jiǎn)單分析了module.exports模塊化的定義與引用相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-12-12JS對(duì)HTML標(biāo)簽select的獲取、添加、刪除操作
HTML標(biāo)簽中的select在使用過(guò)程中很頻繁,在本文將為大家介紹下使用js是如何操作的,下面有個(gè)不錯(cuò)的示例,感興趣的朋友不要錯(cuò)過(guò)2013-10-10利用JS獲取IE客戶端IP及MAC的實(shí)現(xiàn)好象不可以
利用JS獲取IE客戶端IP及MAC的實(shí)現(xiàn)好象不可以...2007-01-01JavaScript使用Web Worker解析CSV文件的操作方法
在處理大型 CSV 文件時(shí),直接在主線程中解析可能會(huì)導(dǎo)致頁(yè)面卡頓,影響用戶體驗(yàn),使用 Web Worker 可以將計(jì)算密集型任務(wù)移到后臺(tái)線程,避免阻塞主線程,從而提升應(yīng)用的響應(yīng)速度,所以本文給大家介紹了JavaScript使用Web Worker解析CSV文件的操作方法,需要的朋友可以參考下2025-03-03前端常見(jiàn)問(wèn)答之flat()和flatMap()有哪些不同
這篇文章主要介紹了JavaScript中的flat()和flatMap()方法,解釋了它們的功能、使用方法和應(yīng)用場(chǎng)景,flat()用于將嵌套數(shù)組壓平,而flatMap()則是在壓平的同時(shí)對(duì)每個(gè)元素進(jìn)行轉(zhuǎn)換,需要的朋友可以參考下2024-11-11前端bug調(diào)試的方法技巧及常見(jiàn)錯(cuò)誤
這篇文章主要介紹了編程中常見(jiàn)的報(bào)錯(cuò)和Bug,以及調(diào)試的重要性,調(diào)試的基本流程是通過(guò)縮小范圍來(lái)定位問(wèn)題,并給出了推測(cè)法、刪除代碼法、console調(diào)試和debugger調(diào)試等方法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2025-03-03