首先,我想到的是另一個建立一個結果數組,用來儲存原始數組中不重複的資料。遍歷原始陣列依序跟著結果陣列中的元素進行比較,偵測是否重複。於是乎,我寫出瞭如下代碼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中的陣列方法indexOf 可以檢索陣列元素。於是我又使用indexOf 方法取代了第二層循環,寫出瞭如下程式碼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行了,簡潔多了。高三數學大題解法一般都不只一種的啊,然後我就繼續再想其他方法了。 indexOf 方法的意思是搜尋整個陣列中具有給定值的元素,傳回找到的第一個元素的索引,沒有找到就傳回-1 ,第一個參數就是要搜尋的值,第二個參數可選:它指定數組中的一個索引,從那裡開始搜索,如果省略這個參數,則從頭開始搜索。思維一發散,想到了前面方法都是檢測值是否重複的,現在有了indexOf 方法不就可以根據檢測到的每個元素的第一次出現時的索引和這個元素自身的索引值比較相等來判斷是否重複嘛。所以,我又寫出了代碼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; }
寫完這個,又繼續想了想,實在是想不出其他方法了,這三個方法都是很基礎的方法。於是,我就去對照答案,檢驗自己了。一看答案,發現自己還是真實太弱了,簡單的問題還是有些奇思妙想的。下面不是自己想的了,就不再說太多我的心路歷程了。廢話不多說,直接上經典的答案 解析了。
首先,先說一個演算法中常說的以空間換時間的解法,保持隊形,我們就叫它代碼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; }
這個方法中在遍歷原始陣列時用一個物件 obj 的屬性來保存原始陣列中元素的值。同時這個屬性的值是一個數組,用來儲存這個屬性的類型,這可以把原始數組中類似數字1元素和字串‘1'的元素區分開。這個方法透過額外建構一個物件的方式降低了上面三種方法中indexOf方法所花費的時間,可以說較為高效吧。
如果你已經滿足於上面所說的以空間換時間的高效方法而不繼續看下去的話,那就大錯特錯了,好戲總在後頭嘛。現在好戲開場,毫無疑問,就是代碼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呢?這程式碼是錯的吧,這個真的能去重嗎?是的,起初我都沒看懂這程式碼,看了解析後又看了一遍之後才明白。那麼,沒看懂的看官也要認真的看解析了:第一層從前往後遍歷原始數組,第二層循環是檢測每個元素是否跟它之後的元素重複,如果它之後有重複元素則跳過它;如果這個元素之後所有元素都跟他不重複了,則把它加到結果陣列中。這個方法實現想法就是:取得無重複的最右一值加到結果數組中,這個跟第一種方法相比也優化了第二層的循環,效率要比它高,不過這個方法的結果數組中元素的順序跟原始數組中元素的順序不一樣了。
看完了程式碼E解析的你是不是已經伸出了大拇指、投放出了敬佩的目光呢? (這些鮮花和榮譽別給我,應該給寫這個方法的大神去)。下面再說最後一個方法:那就是先排序,再去重。舊規矩,它叫做代碼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; }
這個先用陣列的排序方法sort進行陣列元素排序,然後再進行去重工作。
以上就是對javascript數組去重問題的一步步研究,不斷改進程式碼,總共分享了六段程式碼,希望大家認真學習,能夠有所收穫。