在日常開發(fā)中脸爱,我們可能會遇到去重問題,這篇文章就是為了解決這個問題而寫的未妹。
為了方便使用寇蚊,我們可以直接把封裝的去重函數(shù)直接加入到數(shù)組的prototype中。
方法一:
Array.prototype.clearRepeat = function()?{
var arr =?[];?//定義一個臨時(shí)數(shù)組
for(var i = 0; i < this.length; i++)?{
//通過遍歷判斷當(dāng)前數(shù)組下標(biāo)為i的元素是否保存到臨時(shí)數(shù)組中
//如果保存过蹂,則跳過茬腿,否則保存到臨時(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();????//結(jié)果為[1, 6, 8, 9,?"a"]
方法二:
Array.prototype.clearRepeat = function()?{
var arr =?[this[0]];?//直接定義結(jié)果數(shù)組
for(var i = 1; i < this.length; i++)?{?//從第二項(xiàng)開始遍歷當(dāng)前數(shù)組
//對元素進(jìn)行判斷:
//如果當(dāng)前數(shù)組元素在此數(shù)組中第一次出現(xiàn)的位置不是i
//則第i項(xiàng)是重復(fù)的,否則直接存入結(jié)果數(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();????//結(jié)果為[1, 6, 8, 9,?"a"]
上面兩種方法不推薦使用化戳,因?yàn)閕ndexOf()這個函數(shù)在執(zhí)行的時(shí)候每次都會遍歷一次數(shù)組单料,對性能影響比較大。比較適合小數(shù)據(jù)量的數(shù)組点楼。
方法三:
Array.prototype.clearRepeat = function()?{
var h =?{};?//定義一個hash表
var arr =?[];?//定義一個臨時(shí)數(shù)組
for(var i = 0; i < this.length; i++)?{
//對元素進(jìn)行判斷是否存在表中扫尖,如存在則跳過,否則存入臨時(shí)數(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();????//結(jié)果為[1, 6, 8, 9,?"a"]
上面這種方法使用的是hash表掠廓,把已經(jīng)出現(xiàn)過的元素通過下標(biāo)形式寫入一個Object中换怖,下標(biāo)的引用要比數(shù)組的indexOf()方法搜索節(jié)省時(shí)間。
順便補(bǔ)充下hash表的知識:
哈希表也叫散列表蟀瞧,是根據(jù)關(guān)鍵碼值(key, value)而進(jìn)行訪問的數(shù)據(jù)結(jié)構(gòu)沉颂。它通過把關(guān)鍵碼值映射到表中一個位置來訪問記錄条摸,以加快查找速度。這個映射函數(shù)叫做散列函數(shù)铸屉,存放記錄的數(shù)組叫做散列表钉蒲。
關(guān)于hash表的詳細(xì)知識請點(diǎn)擊這里
通過測試發(fā)現(xiàn)上面這種方法存在一種缺陷,那就是當(dāng)數(shù)組中同時(shí)出現(xiàn)類似于1和“1”這樣的元素時(shí)彻坛,會把“1”這樣的元素被去重子巾。
var test?=?[1,?6,?8,?8,?9,?9,?9,?"a",?"a",?"1"];
test.clearRepeat();????//結(jié)果為[1, 6, 8, 9,?"a"],正確的應(yīng)該為[1, 6, 8, 9,?"a"小压,"1"]
查閱資料發(fā)現(xiàn)原因是因?yàn)椋?/p>
作為下標(biāo)在轉(zhuǎn)換后會變成字符串线梗,那么對于1和“1”這樣不同類型的值會對應(yīng)到同一個下標(biāo)而被去重。
修改后的代碼:
Array.prototype.clearRepeat = function()?{
var h =?{};?//定義一個hash表
var arr =?[];?//定義一個臨時(shí)數(shù)組
for(var i = 0; i < this.length; i++)?{
//對元素進(jìn)行判斷是否存在表中怠益,如存在則跳過仪搔,否則存入臨時(shí)數(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();????//結(jié)果為[1, 6, 8, 9,?"a",?"1"]
方法四:
Array.prototype.clearRepeat = function()?{
this.sort();?//數(shù)組排序
var arr =?[this[0]];?//定義結(jié)果數(shù)組
for(var i = 1; i < this.length; i++)?{?//從第二項(xiàng)開始遍歷當(dāng)前數(shù)組
//判斷兩個相鄰元素是否相等,如果相等說明數(shù)據(jù)重復(fù)蜻牢,否則將元素寫入結(jié)果數(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();????//結(jié)果為[1, 6, 8, 9,?"a"]
上面這種方法先將數(shù)組排序烤咧,然后比較相鄰兩個元素是否相等,若相等說明重復(fù)抢呆。數(shù)組排序采用的原生sort()煮嫌。
關(guān)于數(shù)組排序方法請點(diǎn)擊這里
上面四種方法的優(yōu)劣和性能讀者可以自行去測試。
如果你在本文中發(fā)現(xiàn)錯誤或者有異議的地方抱虐,可以在評論區(qū)留言昌阿,謝謝!