在日常開發(fā)中,我們可能會遇到去重問題,這篇文章就是為了解決這個問題而寫的。
為了方便使用,我們可以直接把封裝的去重函數(shù)直接加入到數(shù)組的prototype中。
方法一:
Array.prototype.clearRepeat = function()?{
var arr =?[];?//定義一個臨時數(shù)組
for(var i = 0; i < this.length; i++)?{
//通過遍歷判斷當前數(shù)組下標為i的元素是否保存到臨時數(shù)組中
//如果保存,則跳過,否則保存到臨時數(shù)組
if(arr.indexOf(this[i])?==?-1)?{
arr.push(this[i]);
}
}
return arr;
};
var test =?[1, 6, 8, 8, 9, 9, 9,?"a",?"a"];
test.clearRepeat();????//結果為[1, 6, 8, 9,?"a"]
方法二:
Array.prototype.clearRepeat = function()?{
var arr =?[this[0]];?//直接定義結果數(shù)組
for(var i = 1; i < this.length; i++)?{?//從第二項開始遍歷當前數(shù)組
//對元素進行判斷:
//如果當前數(shù)組元素在此數(shù)組中第一次出現(xiàn)的位置不是i
//則第i項是重復的,否則直接存入結果數(shù)組
if(this.indexOf(this[i])?== i)?{
arr.push(this[i]);
}
}
return arr;
};
var test =?[1, 6, 8, 8, 9, 9, 9,?"a",?"a"];
test.clearRepeat();????//結果為[1, 6, 8, 9,?"a"]
上面兩種方法不推薦使用,因為indexOf()這個函數(shù)在執(zhí)行的時候每次都會遍歷一次數(shù)組,對性能影響比較大。比較適合小數(shù)據(jù)量的數(shù)組。
方法三:
Array.prototype.clearRepeat = function()?{
var h =?{};?//定義一個hash表
var arr =?[];?//定義一個臨時數(shù)組
for(var i = 0; i < this.length; i++)?{
//對元素進行判斷是否存在表中,如存在則跳過,否則存入臨時數(shù)組
if(!h[this[i]])?{
h[this[i]]?= true;?//存入hash表
arr.push(this[i]);
}
}
return arr;
};
var test =?[1, 6, 8, 8, 9, 9, 9,?"a",?"a"];
test.clearRepeat();????//結果為[1, 6, 8, 9,?"a"]
上面這種方法使用的是hash表,把已經(jīng)出現(xiàn)過的元素通過下標形式寫入一個Object中,下標的引用要比數(shù)組的indexOf()方法搜索節(jié)省時間。
順便補充下hash表的知識:
哈希表也叫散列表,是根據(jù)關鍵碼值(key, value)而進行訪問的數(shù)據(jù)結構。它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找速度。這個映射函數(shù)叫做散列函數(shù),存放記錄的數(shù)組叫做散列表。
通過測試發(fā)現(xiàn)上面這種方法存在一種缺陷,那就是當數(shù)組中同時出現(xiàn)類似于1和“1”這樣的元素時,會把“1”這樣的元素被去重。
var test?=?[1,?6,?8,?8,?9,?9,?9,?"a",?"a",?"1"];
test.clearRepeat();????//結果為[1, 6, 8, 9,?"a"],正確的應該為[1, 6, 8, 9,?"a","1"]
查閱資料發(fā)現(xiàn)原因是因為:
作為下標在轉換后會變成字符串,那么對于1和“1”這樣不同類型的值會對應到同一個下標而被去重。
修改后的代碼:
Array.prototype.clearRepeat = function()?{
var h =?{};?//定義一個hash表
var arr =?[];?//定義一個臨時數(shù)組
for(var i = 0; i < this.length; i++)?{
//對元素進行判斷是否存在表中,如存在則跳過,否則存入臨時數(shù)組
var type = typeof this[i];
if(!h[this[i]?+ type])?{
h[this[i]?+ type]?= true;
arr.push(this[i]);
}
}
return arr;
};
var test =?[1, 6, 8, 8, 9, 9, 9,?"a",?"a",?"1"];
test.clearRepeat();????//結果為[1, 6, 8, 9,?"a",?"1"]
方法四:
Array.prototype.clearRepeat = function()?{
this.sort();?//數(shù)組排序
var arr =?[this[0]];?//定義結果數(shù)組
for(var i = 1; i < this.length; i++)?{?//從第二項開始遍歷當前數(shù)組
//判斷兩個相鄰元素是否相等,如果相等說明數(shù)據(jù)重復,否則將元素寫入結果數(shù)組
if(this[i]?!== arr[arr.length - 1])?{
arr.push(this[i]);
}
}
return arr;
};
var test =?[1, 6, 8, 8, 9, 9, 9,?"a",?"a"];
test.clearRepeat();????//結果為[1, 6, 8, 9,?"a"]
上面這種方法先將數(shù)組排序,然后比較相鄰兩個元素是否相等,若相等說明重復。數(shù)組排序采用的原生sort()。
上面四種方法的優(yōu)劣和性能讀者可以自行去測試。
如果你在本文中發(fā)現(xiàn)錯誤或者有異議的地方,可以在評論區(qū)留言,謝謝!