總得來說面試的過程還是收穫了不少,主要是認清自己的差距到底有多大,知識面到底有多窄,適當打擊一下自信心還是有必要的。在這裡做一次全面的總結,關於javascript的數組去重問題。
考慮一個問題由簡到繁相對容易接受一點,首先假設要去重的數組是比較簡單的,例如:
複製代碼 代碼如下:
var arr=[1,2,2,3,'5',6,5,'',' ']
這個數組只包含了數字,字串兩種類型。我們給數組原型上面添加去重的方法distinct,用第一種很容易想到的方法來實現,當然也是很笨很直接的,把這個數組複製一份然後迴圈兩個數組,對比當前值與後面所有的值是否相等,如果與後面所有值都不等則把該值存到新數組裡,如此最後再返回該新數組。方法如下:
複製代碼 代碼如下:
//第一種方法
Array.prototype.distinct=function(){
var clone,newArr=[],n=0;
if(this.length<2)return;
clone=this;
for(var i=0,len=this.length;i<len;i++){
for(var j=i+1,len2=clone.length;j<len2;j++){
if(this[i]!==clone[j]){
n++;
}
}
if(n==(len-i-1)){
newArr.push(this[i])
}
n=0;
}
return newArr;
}
console.log([1,2,2,3,'5',6,5,'',' '].distinct());
/*獲得被check的radio的值*/
function GetRadioValue(RadioName){
var obj;
obj=document.getElementsByName(RadioName);
if(obj!=null){
var i;
for(i=0;i<obj.length;i++){
if(obj[i].checked){
return obj[i].value;
}
}
}
return null;
}
/*設定被選中屬性*/
function SetRadioCheck(RadioName,i){
var obj;
obj=document.getElementsByName(RadioName);
obj[i].setAttribute("checked","checked");
}
基本可以滿足我們的需求,對這樣簡單的類型比較確實不用費太多的腦經,但如果數組很長呢?如此遍曆數組,數組長度為n,那麼時間複雜度為n*n。顯然該方法效能還有待提升。接下來是第二種方法,用到數組排序,在排序的過程去除重複的值。
複製代碼 代碼如下:
//第二種方法
Array.prototype.distinct=function(){
var newArr=this.concat().sort(),self=this;
newArr.sort(function(a,b){
var n;
if(a===b){
n=self.indexOf(a);
self.splice(n,1);
}
});
return self;
}
console.log([1,2,2,3,'5',6,5,6,6,15,5,'5',5,'',' '].distinct());
這樣代碼看起來似乎短了很多,甚至連一個for迴圈都沒有,但是sort得效率也高不到哪裡去。再來看看第三種實現方法,用到的對象屬性不會重名的原理
複製代碼 代碼如下:
//第三種方法
Array.prototype.distinct=function(){
var newArr=[],obj={};
for(var i=0,len=this.length;i<len;i++){
if(!obj[this[i]]){
newArr.push(this[i]);
obj[this[i]]='new';
}
}
return newArr;
}
console.log([1,2,2,3,'5',6,5,6,6,15,5,'5',5,'',' '].distinct());
第三種方法運行看下結果,會發現跟上面的方法實現的結果不一致,細看原來它把數字5和字串5當成重複的值給去掉了。看來類型必須儲存起來然後再判斷是否相等,這樣便有了下面的第三種方法的補充版
複製代碼 代碼如下:
//第三種方法補充版
Array.prototype.distinct=function(){
var newArr=[],obj={};
for(var i=0,len=this.length;i<len;i++){
if(!obj[typeof(this[i])+this[i]]){
newArr.push(this[i]);
obj[typeof(this[i])+this[i]]='new';
}
}
return newArr;
}
上面舉的例子是很簡單的類型,我們拿更複雜的類型來測試一下
複製代碼 代碼如下:
console.log([1,null,2,{a:'vc'},{},'5',6,5,6,{a:'vv'},15,5,'5',5,'',' ',[1],[1],[1,2],,].distinct());
發現{a:'vc'},{},{a:'vv'}這些不同的對象還是會被剔除掉,如果數組裡面有對象則要繼續遍曆對象裡面的屬性和值,繼續第三種方法的加強
複製代碼 代碼如下:
//第三種方法加強版
Array.prototype.distinct=function(){
var sameObj=function(a,b){
var tag = true;
if(!a||!b)return false;
for(var x in a){
if(!b[x])
return false;
if(typeof(a[x])==='object'){
tag=sameObj(a[x],b[x]);
}else{
if(a[x]!==b[x])
return false;
}
}
return tag;
}
var newArr=[],obj={};
for(var i=0,len=this.length;i<len;i++){
if(!sameObj(obj[typeof(this[i])+this[i]],this[i])){
newArr.push(this[i]);
obj[typeof(this[i])+this[i]]=this[i];
}
}
return newArr;
}
用上面的例子測試發現基本木有問題,當然測試還可以更加變態更加糾纏,這裡就不去深究了,目前來看此篇方法在網上屬於比較齊全的,如果有更好更完善的方法請不吝賜教。