<h1>數(shù)組去重</h1>
<blockquote>
<p>之前一段時(shí)間一直在準(zhǔn)備面試, 因而博客太久沒更新; 現(xiàn)在基本知識(shí)點(diǎn)都復(fù)習(xí)完畢, 接下來就分享下 面試的一些常見問題:
去正規(guī)的互聯(lián)網(wǎng)公司筆試、面試有很大的概率會(huì)碰到 使用javascript實(shí)現(xiàn)數(shù)組去重的編碼問題:下面筆者就介紹幾種數(shù)組去重的方法</p>
</blockquote>
<h2>利用對(duì)象的鍵值對(duì)方法去重</h2>
<p>思路:</p>
<ol>
<li>我們把數(shù)組中的每一項(xiàng)的值當(dāng)做一個(gè)對(duì)象的屬性名和屬性值存儲(chǔ)起來</li>
<li>但是我們?cè)诖鎯?chǔ)之前,我們首先判斷當(dāng)前這一項(xiàng)(N)是否在對(duì)象中已經(jīng)存在了->obj[N],如果值是N(我們已經(jīng)把值和屬性名存儲(chǔ)成是一樣的),說明對(duì)象中已經(jīng)存在這一項(xiàng)了,如果值是undefined,說明對(duì)象中還沒有這一項(xiàng)</li>
<li>如果值是N,說明對(duì)象中已經(jīng)存在這一項(xiàng),同時(shí)也說明在N之前數(shù)組中已經(jīng)出現(xiàn)過一次N了,即這一項(xiàng)已經(jīng)重復(fù),我們從數(shù)組中把這一項(xiàng)刪掉,如果值是undefined,說明對(duì)象中還沒有這一項(xiàng),也說明這一項(xiàng)以前沒有在數(shù)組中出現(xiàn)過,我們把當(dāng)前值存儲(chǔ)進(jìn)去即可</li>
</ol>
<p>```</p>
<p>比如:</p>
<p>var obj = {};
obj[1] -> undefined {1:1}
obj[2] -> undefined {2:2}
obj[3] -> undefined {3:3}
obj[2] -> 2 {1:1}
obj[1] -> 說明第四項(xiàng)2在之前出現(xiàn)過,我們把第四項(xiàng)刪除</p>
<p>```
思路我們就分析完了,現(xiàn)在具體寫這個(gè)方法</p>
<p>```
var ary = [1,2,3,2,3,2,3,1,2,3,4,2,3,1];
var obj = {};
for(var i=0;i<ary.length;i++){
var cur = ary[i];//此處是遍歷數(shù)組 ary[1]=1,2,3,2......同是
把這個(gè)值賦值給cur即cur=1,2,3,2...此時(shí)我們就能讓屬性名和屬性值相
同。var 1= 1;var 2 = 2 ...;
if(obj[cur]==cur){//我們把屬性名和屬性值,存儲(chǔ)到對(duì)象中,即
obj[1]和1,如果對(duì)象中obj[1]的值和你存儲(chǔ)cur的值相同,則滿足此條
件,但是我們存儲(chǔ)第一項(xiàng)的時(shí)候?qū)ο笾衞bj[1]還沒有值,即undefined,所以
第一項(xiàng)不滿足。如果滿足,我們就刪除數(shù)組中的這一項(xiàng)
ary.splice(i,1);//即把第i項(xiàng)刪除->splice方法,從第i項(xiàng)刪除一
個(gè),注意,刪除后,會(huì)有數(shù)組塌陷,所以我們要i--
i--;</p>
<pre><code> }else {//不滿足if條件,走此步。
obj[cur] = cur;//把數(shù)組里的值,存儲(chǔ)到對(duì)象中。以便用此條件給后面
的條件進(jìn)行判斷
}
}
console.log(ary);
</code></pre>
<p>```</p>
<p>結(jié)果為 [1, 2, 3, 4]</p>
<p>這是一種方法,但是這種方法并不完美,因?yàn)橛袛?shù)組塌陷問題,對(duì)系統(tǒng)性能有一定影響</p>
<p>下面這是升級(jí)改進(jìn)的方法。
在上面的思路上,我們可以不用splice方法,如果對(duì)象中屬性名和屬性值一樣,我們可以把比較的當(dāng)前項(xiàng),用最后面的一項(xiàng)替換掉,然后把最后一項(xiàng)刪除即可,注意:仍要用i--;因?yàn)槟眠^來,還沒有比較,還要再次走一遍if條件對(duì)新值進(jìn)行比較。</p>
<p>```
var ary = [1,2,3,2,3,2,3,1,2,3,4,2,3,1];
var obj = {};
for(var i=0;i<ary.length;i++){
var cur = ary[i];
if(obj[cur]==cur){
ary[i] = ary[ary.length-1];//我們把最后一項(xiàng),替換掉當(dāng)前項(xiàng)
ary.length--;//刪除掉最后一項(xiàng),即把數(shù)組長(zhǎng)度縮小一位即可。
i--;</p>
<pre><code> }else {//不滿足if條件,走此步。
obj[cur] = cur;//把數(shù)組里的值,存儲(chǔ)到對(duì)象中。以便用此條件給后面的條件進(jìn)行判斷
}
}
console.log(ary);
</code></pre>
<p>```
結(jié)果為 [1, 2, 3, 4]</p>
<p>以上方法是在原數(shù)組中操作,其實(shí)我感覺并不是最好的方法,假如在數(shù)組中有不同類型的相同值得項(xiàng)呢?我們可以另定義一個(gè)新數(shù)組,然后在加上類型的判斷,這種方法就不很細(xì)的解讀了。寫上以便讀者參考</p>
<p><code>var ary = [3,2,3,1,4,true,false,"3","22","2",2];
function noRepeat(ary) {
var newAry = [];
var obj = {};
for(var i=0;i<ary.length;i++){
if(!(obj[ary[i]+typeof ary[i]])){//此處將obj的屬性值用值+類型的方式存儲(chǔ)起來,比如第一項(xiàng)obj[3number];如果該屬性名的值不存在,則在此處執(zhí)行
newAry.push(ary[i]);
obj[ary[i]+typeof ary[i]] = 1;//此處把該對(duì)象的屬性名的值隨便賦值成一個(gè)東東,比如1,以后判斷的時(shí)候,證明該屬性名的值存在
}
}
return newAry;// 此函數(shù)的最終目的是返回新的數(shù)組。
}
var res = noRepeat(ary);//執(zhí)行此函數(shù),并賦值給res,即res = newAry;
console.log(res);</code></p>
<p>結(jié)果為 [3, 2, 1, 4, true, false, "3", "22", "2"]</p>