【JavaScript寫法】數組去重 在進行項目開發的時候,有時候需要把一些前端的數組進行去重處理,得到一個去重後的數據,然後再進行相關的操作,這也是在前端面試中經常出現的問題 ...
在進行項目開發的時候,有時候需要把一些前端的數組進行去重處理,得到一個去重後的數據,然後再進行相關的操作,這也是在前端面試中經常出現的問題
數組去重的多種方法:
- 利用 ES6 Set 去重
- 利用 for 嵌套 for,然後 splice 去重
- 利用 indexOf 去重
- 利用 sort() 去重
- 利用對象的屬性不能相同的特點進行去重
- 利用 includes 去重
- 利用 hasOwnProperty 去重
- 利用 filter 去重
- 利用遞歸去重
- 利用 Map 數據結構去重
- 利用 reduce+includes 去重
- [...new Set(arr)] 去重
數組去重
利用 ES6 Set 去重數組
Set 自帶的特性,數據不重覆
Array.from()
方法將Set
對象轉換為數組,並返回該數組作為去重後的新數組。時間複雜度為 O(n),因為
Set
對象只需要遍歷一次原數組即可完成去重操作註:無法判斷
{}
重覆的情況
const _deleteRepeat = array => {
return Array.from(new Set(array))
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log("去重後:=>",_deleteRepeat(arr));
//去重後:=> [ 1, 15, "abc", true, false, undefined, null, NaN, {}, {} ]
利用 for 嵌套 for,然後 splice 去重
雙層迴圈,外層迴圈元素, 內層迴圈時比較值。值相同時,則刪去這個值。(比較相鄰兩個數如果重覆用 splice 刪除)
時間複雜度為 O(n^2),因為兩層迴圈需要對所有元素進行比較。因此,這種方法在處理大型數組時可能會導致性能問題。⚠️
註:無法判斷
NaN
及{}
重覆的情況
const _deleteRepeat = array => {
for (let i = 0; i < array.length; i++) {
for (let j = i + 1; j < array.length; j++) {
if (array[i] === array[j]) {
array.splice(j, 1);
j --;
}
}
}
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
_deleteRepeat(arr)
console.log(arr)
// [ 1, 15, "abc", true, false, undefined, null, NaN, NaN, {}, {}]
利用 indexOf 去重
新建⼀個空的結果數組, for 迴圈原數組, 判斷結果數組是否存在當前元素, 如果有相同的值則跳過,不相同則 push 進數組
時間複雜度為 O(n^2),因為
indexOf()
方法需要對所有元素進行比較。因此,這種方法在處理大型數組時可能會導致性能問題。⚠️註:無法判斷
NaN
及{}
重覆的情況
const _deleteRepeat = array => {
// 聲明一個空數組,用indexOf尋找如果沒有該元素則加入新數組
let newArray = [];
array.forEach(item => {
if(newArray.indexOf(item) === -1) {
newArray.push(item)
}
});
return newArray;
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr));
// [ 1, 15, "abc", true, false, undefined, null, NaN, NaN, {}, {} ]
利用 sort() 去重
利用sort()排序方法,然後根據排序後的結果進行遍歷及相鄰元素比對
時間複雜度為 O(n log n),因為需要對所有元素進行排序操作。因此,這種方法在處理大型數組時可能會導致性能問題。⚠️
註:無法判斷
NaN
及{}
重覆的情況
const _deleteRepeat = array => {
if (!Array.isArray(array)) {
console.log("type error")
return
}
array = array.sort();
let newArray = [array[0]]
for (let i = 1; i < array.length; i++) {
if (array[i] !== array[i - 1]) {
newArray.push(array[i])
}
}
return newArray
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, NaN, NaN, {}, {}, "abc", false, null, true, undefined ]
利用對象的屬性不能相同的特點進行去重
它會遍歷輸入的數組,將每個元素作為對象的屬性名,如果該屬性名在對象中不存在,則將其添加到對象中並將該元素添加到新數組中;如果該屬性名已經存在,則不進行任何操作。最終返回去重後的新數組。
註:只能去除數組中的重覆值,而不能去除數組中的重覆元素(即包含多個值的元素)。如果需要去除數組中的重覆元素,可以使用其他方法,比如使用 Set 數據結構或者雙重迴圈等。⚠️
const _deleteRepeat = array => {
if (!Array.isArray(array)) {
console.log("type error")
return
}
let newArray = [];
let obj = {};
array.forEach(item => {
if(!obj[item]) {
obj[item] = true;
newArray.push(item);
}
})
return newArray;
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, "abc", true, false, undefined, null, NaN, {} ]
利用 includes 去重
聲明一個空數組,用 includes 尋找如果沒有該元素則加入新數組
時間複雜度為 O(n^2),因為需要對所有元素進行比較和查找操作。因此,這種方法在處理大型數組時可能會導致性能問題。⚠️
註:無法判斷
{}
重覆的情況
const _deleteRepeat = array => {
let newArray = [];
array.forEach(item => {
if (!newArray.includes(item)) {
newArray.push(item)
}
});
return newArray
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, "abc", true, false, undefined, null, NaN, {}, {} ]
利用 hasOwnProperty 去重
利用 hasOwnProperty 檢查對象是否具有指定屬性
typeof {}+{} 為 object[object Object],判斷有沒有空對象,已經有的話 return false,沒有就作為對象的屬性加進去,值為 true
時間複雜度為 O(n^2),因為需要對所有元素進行比較和查找操作。因此,這種方法在處理大型數組時可能會導致性能問題。⚠️
const _deleteRepeat = array => {
let newArray = [];
let obj = {};
newArray = array.filter(item => {
return obj.hasOwnProperty(typeof item + item) ? false : obj[typeof item +item] = true
});
return newArray
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, "abc", true, false, undefined, null, NaN, {} ]
利用 filter 去重
該函數使用了
filter()
方法來篩選出數組中的唯一元素。在filter()
方法中,傳入了一個回調函數,該回調函數接受兩個參數:item
(當前遍歷到的元素)和index
(當前元素的索引)。在回調函數內部,我們使用
indexOf()
方法查找該元素在原數組中第一次出現的位置。如果該位置與當前迴圈的索引相同,則說明該元素是第一次出現,需要保留;否則,說明該元素已經出現過一次,需要過濾掉。註:無法判斷
{}
重覆的情況(無法判斷NaN
)
const _deleteRepeat = array => {
return array.filter((item, index) => {
return array.indexOf(item) === index
})
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, "abc", true, false, undefined, null, {}, {} ]
利用遞歸去重
時間複雜度是 O(n^2),因為在每次遞歸調用時都需要遍歷整個數組來查找重覆元素。因此,這種方法在處理大型數組時可能會導致性能問題。⚠️
註:無法判斷
{}
、NaN
重覆的情況
const _deleteRepeat = array=> {
let len = array.length;
// 排序後更加方便去重
array = array.sort();
const loop = index => {
if (index >= 1) {
if (array[index] === array[index - 1]) {
array.splice(index, 1);
}
// 遞歸loop,然後數組去重
loop(index - 1);
}
}
loop(len - 1);
return array;
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, NaN, NaN, {}, {}, "abc", false, null, true, undefined ]
利用Map數據結構去重
創建⼀個空 Map 數據結構, 遍歷需要去重的數組, 把數組的每⼀個元素作為 key 存到 Map 中。由於 Map 中不會出現相同的 key 值,所以最終得到的就是去重後的結果
時間複雜度為 O(n),因為只需要對所有元素進行一次遍歷和查找操作。因此,這種方法在處理大型數組時具有較好的性能。
註:無法判斷
{}
重覆的情況
const _deleteRepeat = array => {
let newArray = [];
let map = new Map();
array.forEach(item => {
if (!map.has(item)) {
map.set(item, true);
newArray.push(item);
}
});
return newArray
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, "abc", true, false, undefined, null, NaN, {}, {} ]
利用 reduce+includes 去重
reduce()
方法遍歷原數組對於每個元素
item
,我們使用includes()
方法來檢查該元素是否已經存在於累加器數組accumulator
中。如果不存在,則使用push()
方法將該元素添加到累加器數組中。最後,我們返回累加器數組作為去重後的新數組。時間複雜度為 O(n^2),因為需要對所有元素進行比較和查找操作。因此,這種方法在處理大型數組時可能會導致性能問題。⚠️
註:無法判斷
{}
重覆的情況
const _deleteRepeat = array => {
return array.reduce((accumulator, item) => {
if (!accumulator.includes(item)) {
accumulator.push(item);
}
return accumulator;
}, []);
};
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, "abc", true, false, undefined, null, NaN, {}, {} ]
[...new Set(arr)]
利用擴展運算符
...
和Set
對象去重數組時間複雜度為 O(n),
Set
對象只需要遍歷一次原數組即可完成去重操作註:無法判斷
{}
重覆的情況
const _deleteRepeat = array => {
return [...new Set(array)];
}
let arr = [1, 1, 15, 15, 'abc', 'abc',
true, true, false, false, undefined, undefined,
null, null, NaN, NaN, {}, {}];
console.log(_deleteRepeat(arr))
// [ 1, 15, "abc", true, false, undefined, null, NaN, {}, {} ]