數組去重的方式有不少種,咱們先拿出3種比較簡單的進行學習;javascript
原理:依次遍歷數組中的每一項,拿當前項和其「後面」的每一項進行比較,若是後面中有和他相同的,則說明這項是重複的,咱們把後面中重複的這一項刪除掉便可java
let arr = [1, 1, 1, 2, 2, 3, 2, 2, 1, 2, 3, 2, 1, 2, 2, 3];
//====外層循環控制每一次拿出一項和其後面的比
// i < arr.length - 1 最後一項不須要再拿出來了,由於每一次都是和當前項後面的比較,而最後一項後面沒有任何的東西,因此也就沒有必要再拿出來比較了
for (let i = 0; i < arr.length - 1; i++) {
// 每一次拿出來要和後面依次比較的那一項
let item = arr[i];
//====裏層循環控制和當前項後面的每一項逐一比較
// let j = i + 1 從當前項的後一項開始逐一比較便可
for (let j = i + 1; j < arr.length; j++) {
if (item === arr[j]) {
// 當前項和後面中的某一項相等了,此時咱們把後面中的這一項從原始數組中刪除掉
arr.splice(j, 1);
j--; //=>刪除完,先讓j--,而後在j++,至關於沒加沒減,下一輪仍是從當前索引開始比較,這樣防止數組塌陷帶來的問題
}
}
}
複製代碼
解決完
splice
引發的塌陷問題後咱們已經能夠實現想要的效果,可是根據上圖咱們能夠知道,數組
- 在刪除重複項後後面每一項的索引都會向前提一位,這樣(若是刪除的這一項後面還有1000萬項,那麼這1000萬項的索引都要向前提一位)會大大的消耗性能,
- 因此咱們須要作進一步的優化處理;
for (let i = 0; i < arr.length - 1; i++) {
let item = arr[i];
for (let j = i + 1; j < arr.length; j++) {
if (item === arr[j]) {
// 用最後一項替換當前項
arr[j] = arr[arr.length - 1];// 原始數組中的順序會變化,可是不會致使索引前置這種狀況(性能好)
// 最後一項刪掉
arr.length--;
// 下一輪還和這一項比(由於這一項已經變爲最新的最後一項了)
j--;
}
}
}
console.log(arr);
複製代碼
原理:利用對象中屬性名不能重複的特色,先創建一個空對象,而後依次循環數組中的每一項,把此項做爲obj對象的屬性名和屬性值,在添加的時候,若是這個屬性名對應的值已經存在,說明此項重複,刪除掉此項瀏覽器
let arr = [1, 2, 3, 1, 1, 4, 2, 3];
let obj = {};
for (let i = 0; i < arr.length; i++) {
// 把每一次循環獲得的當前項,做爲對象的屬性名和屬性值存儲進去
let item = arr[i];
if (obj[item] !== undefined) {
// 證實對象中有這個屬性(也就是以前存儲過,數組中以前就有這個值),當前值是重複的,咱們須要把當前這項的值刪掉便可
arr[i] = arr[arr.length - 1];
arr.length--;
i--;
continue;
}
obj[item] = item;
}
console.log(arr);
複製代碼
10
和字符串'10'
,則也會認爲是重複的(對象中的屬性名是數字和字符串沒啥區別);undefined
可能也會出現問題....原理:建立一個新數組,遍歷原數組,若是新數組中沒有那一項的話,就把它
push
進去性能優化
let arr=[1,2,1,3,3,2,3];
let newAry=[];
/*把原數組中的每一項,只要在新數組中沒存在過,咱們就把它放進去,最後newAry就是我們最終要的數組*/
for(let i=0;i<arr.length;i++){
let item=arr[i];
if(newAry.indexOf(item)==-1){
newAry.push(item);
}
}
arr = newAry;
console.log(arr);
複製代碼
/* ES6中沒有提供現成的去重辦法,可是提供了一些去重的方式 :Set數據結構*/
let obj = { y: 200 };
let arr = [obj, 1, 2, 3, 1, obj, 1, 4, 2, 3, '3', { x: 100 }, { x: 100 }];
arr = Array.from(new Set(arr));
console.log(arr);
複製代碼