詳解javascript數(shù)組去重問題
首先,我想到的是另建一個結(jié)果數(shù)組,用來存儲原始數(shù)組中不重復(fù)的數(shù)據(jù)。遍歷原始數(shù)組依次跟結(jié)果數(shù)組中的元素進行比較,檢測是否重復(fù)。于是乎,我寫出了如下代碼A:
Array.prototype.clearRepetitionA = function(){ var result = []; var isRepetition; for(var i=0; i<this.length; i++){ isRepetition = false; for(var j=0; j<result.length; j++){ if(this[i] === result[j]){ isRepetition = true; break; } } if(!isRepetition){ result.push(this[i]); } } return result; }
寫完之后,忽然想起來前幾天剛看的ECMAScript 5中的數(shù)組方法indexOf 可以檢索數(shù)組元素。于是我又使用indexOf 方法替代了第二層循環(huán),寫出了如下代碼B:
Array.prototype.clearRepetitionB = function(){ var result = []; for(var i=0; i<this.length; i++){ if(result.indexOf(this[i]) == -1){ result.push(this[i]); } } return result; }
代碼一下子從17行變成了9行了,簡潔多了。高三數(shù)學(xué)大題解法一般都不止一種的啊,然后我就繼續(xù)再想其他方法了。indexOf 方法的意思是搜索整個數(shù)組中具有給定值的元素,返回找到的第一個元素的索引,沒有找到就返回 -1 ,第一個參數(shù)就是要搜索的值,第二個參數(shù)可選:它指定數(shù)組中的一個索引,從那里開始搜索,如果省略這個參數(shù),則從頭搜索。思維一發(fā)散,想到了前面方法都是檢測值是否重復(fù)的,現(xiàn)在有了indexOf 方法不就可以根據(jù)檢測到的每個元素的第一次出現(xiàn)時的索引和這個元素自身的索引值比較相等來判斷是否重復(fù)嘛。所以,我又寫出了代碼C:
Array.prototype.clearRepetitionC = function(){ var result = [this[0]]; for(var i=1; i<this.length; i++){ if(this.indexOf(this[i]) == i){ result.push(this[i]); } } return result; }
寫完這個,又繼續(xù)想了想,實在是想不出其他方法了,這三個方法都是很基礎(chǔ)的方法。于是,我就去對照答案,檢驗自己了。一看答案,發(fā)現(xiàn)自己還是真實太弱了,簡單的問題還是有些奇思妙想的。下面不是自己想的了,就不再說太多我的心路歷程了。廢話不多說,直接上經(jīng)典的答案+解析了。
首先,先說一個算法中經(jīng)常說的以空間換時間的解法,保持隊形,我們就叫它代碼D吧:
Array.prototype.clearRepetitionD = function(){ var result = []; var obj = {}; var key,type; for(var i=0; i<this.length; i++){ key = this[i]; type = typeof key; if(!obj[key]){ obj[key] = [type]; result.push(key); }else if(obj[key].indexOf(type)){ obj[key].push(type); result.push(key); } } return result; }
這個方法中在遍歷原始數(shù)組時用一個對象 obj 的屬性來保存原始數(shù)組中元素的值。同時這個屬性的值是一個數(shù)組,用來存儲這個屬性的類型,這一點可以把原始數(shù)組中類似數(shù)字1元素和字符串‘1'的元素區(qū)分開。這個方法通過額外構(gòu)建一個對象的方式降低了上面三種方法中indexOf方法所花費的時間,可以說較為高效吧。
如果你已經(jīng)滿足于上面所說的以空間換時間的高效方法而不繼續(xù)看下去的話,那就大錯特錯了,好戲總在后頭嘛?,F(xiàn)在好戲開場,毫無疑問,就是代碼E了:
Array.prototype.clearRepetitionE = function(){ var result = []; for(var i=0; i<this.length; i++){ for(var j=i+1; j<this.length; j++){ if(this[i] === this[j]){ j = ++i; } } result.push(this[i]); } return result; }
代碼D以空間換時間,感覺也就一般般。那么代碼E呢?這代碼是錯誤的吧,這個真的能去重嗎?是的,起初我都沒看懂這代碼,看了解析后又看了一遍之后才明白過來。那么,沒看懂的看官也要認(rèn)真的看解析了:第一層從前往后遍歷原始數(shù)組,第二層循環(huán)是檢測每個元素是否跟它之后的元素重復(fù),如果它之后有重復(fù)元素則跳過它;如果這個元素之后所有元素都跟他不重復(fù)了,則把它添加到結(jié)果數(shù)組中。這個方法實現(xiàn)思路就是:獲取無重復(fù)的最右一值添加到結(jié)果數(shù)組中,這個跟第一種方法相比也優(yōu)化了第二層的循環(huán),效率要比它高,不過這個方法的結(jié)果數(shù)組中元素的順序跟原始數(shù)組中元素的順序不一樣了。
看完了代碼E解析的你是不是已經(jīng)伸出了大拇指、投放出了敬佩的目光呢?(這些鮮花和榮譽別給我,應(yīng)該給寫這個方法的大神去)。下面再說最后一個方法:那就是先排序,再去重。老規(guī)矩,它叫代碼F:
Array.prototype.clearRepetitionF = function(){ this.sort(); var result = [this[0]]; for(var i=1; i<this.length; i++){ if(this[i] !== result[result.length-1]){ result.push(this[i]); } } return result; }
這個先用數(shù)組的排序方法sort進行數(shù)組元素排序,然后再進行去重工作。
以上就是對javascript數(shù)組去重問題的一步步研究,不斷改進代碼,總共分享了六段代碼,希望大家認(rèn)真學(xué)習(xí),能夠有所收獲。
相關(guān)文章
echarts折線圖流動特效的實現(xiàn)全過程(非平滑曲線)
最近因為公司業(yè)務(wù)需求,需要實現(xiàn),當(dāng)Echarts重新加載數(shù)據(jù)時實現(xiàn)動態(tài)效果,下面這篇文章主要給大家介紹了關(guān)于echarts折線圖流動特效實現(xiàn)的相關(guān)資料,需要的朋友可以參考下2023-03-03jstree創(chuàng)建無限分級樹的方法【基于ajax動態(tài)創(chuàng)建子節(jié)點】
這篇文章主要介紹了jstree創(chuàng)建無限分級樹的方法,結(jié)合實例形式分析了jstree基于ajax結(jié)合asp.net后臺動態(tài)創(chuàng)建子節(jié)點實現(xiàn)無限分級樹效果的相關(guān)步驟與操作技巧,需要的朋友可以參考下2016-10-10學(xué)習(xí)javascript面向?qū)ο?掌握創(chuàng)建對象的9種方式
這篇文章主要為大家介紹了創(chuàng)建對象的9種方式,幫助大家更好地學(xué)習(xí)javascript面向?qū)ο?,感興趣的小伙伴們可以參考一下2016-01-01js漢字排序問題 支持中英文混排,兼容各瀏覽器,包括CHROME
這套排序機制同時兼容了IE和ff 可以實現(xiàn)所有瀏覽器下排序的統(tǒng)一哦2011-12-12