距離上次發文,已經有一段時間了,最近工作比較忙,這不眼看快雙十一了,就相當於給大家一些福利吧! 一、什麼是數組去重 簡單說就是把數組中重覆的項刪除掉,你 GET 到了嗎 ?下麵我將簡單介紹下幾種基本的方法及其優缺點。 二、方法彙總 兩層迴圈 無相同值直接 進新數組,有相同的值則直接跳過本次內部迴圈 ...
距離上次發文,已經有一段時間了,最近工作比較忙,這不眼看快雙十一了,就相當於給大家一些福利吧!
一、什麼是數組去重
簡單說就是把數組中重覆的項刪除掉,你 GET 到了嗎 ?下麵我將簡單介紹下幾種基本的方法及其優缺點。
二、方法彙總
- 兩層迴圈
** 無相同值直接 push
進新數組,有相同的值則直接跳過本次內部迴圈 **
/*
* @param {Array} arr -要去重的數組
* @param {Array} result -初始化結果數組
*/
const unique = (arr, result = []) => {
const len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j]) {
// 相等則直接跳過
j = ++i;
}
}
result.push(arr[i]);
}
return result;
}
** 相同的做標記,與新數組作比較,沒有則插入 **
/*
* @param {Array} arr -要去重的數組
* @param {Array} result -初始化結果數組
*/
const unique = (arr, result = []) => {
result.push(arr[0]);
const len = arr.length;
let rLen = result.length;
for (let i = 1; i < len; i++) {
let flag = false;
for (var j = 0; j < rLen; j++) {
if (arr[i] === result[j]) {
flag = true;
break;
}
}
if (!flag) {
rLen++;
result.push(arr[i]);
}
}
return result;
}
** 原地演算法(在數組本身操作) **
const unique = arr => {
const len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j,1);
len--;
j--;
}
}
}
return arr;
};
看似代碼代碼簡單,實則記憶體占用高,不實用
- 單層迴圈
** 對象鍵不能重覆 **
const unique = (arr, result = []) => {
const obj = {};
const len = arr.length;
for (let i = 0; i< len; i++) {
if (!obj[arr[i]]) {
// 鍵沒有,則添加
obj[arr[i]] = 1;
result.push(arr[i]);
}
}
return result;
};
這種方法無法判斷
'1'
和1
等類型,解決方案:
- 添加判斷數據類型,比如
typeof
,obj[typeof arr[i] + arr[i]]
不過這還是判斷不了['1']
和[1]
,因為這被相加後,結果都一樣- 添加
JSON.stringify()
對結果進行去格式化,這時就可以判斷了
** 排序後比較前後兩位,不相等則添加進新數組 **
const unique = (arr, result = []) => {
arr.sort();
result.push(arr[0]);
const len = arr.length;
let rLen = result.length;
for (let i = 1; i < len; i++) {
if (arr[i] !== result[rLen - 1]) {
result.push(arr[i]);
rLen++;
}
}
return result;
}
方法比較直接
** 原地演算法(排序後比較前後兩位,相等則刪除) **
const unique = (arr) => {
arr.sort();
let len = arr.length;
for (let i = 1; i < len; i++) {
if (arr[i] === arr[i - 1]) {
arr.splice(i, 1)
len--;
}
}
return arr;
}
不消耗額外的空間
- 偷懶的節奏
** indexOf
判斷數組元素第一次出現的位置是否相同 **
const unique = (arr, result) => {
arr.forEach((item, index, array) => {
if(array.indexOf(item) === index) {
result.push(item);
}
});
return result;
}
// 使用ES6 filter
const unique = (arr) =>
arr.filter((item, index) => array.indexOf(item) === index);
使用ES6 方法更簡潔性能更好
** indexOf
的ES6 方法通過 includes
判斷新數組中是否有該元素 **
const unique = (arr, result) => {
arr.forEach((item, index, array) => {
if(!result.includes(item)) {
// 或者 result.indexOf(item) === -1
result.push(item);
}
});
return result;
}
建議使用
includes
** Map
數據結構,不懂 Map
的自行解決,傳送門 **
const unique = arr => {
const map = new Map();
return arr.filter((item) => !map.has(item) && map.set(item, 1));
}
對象關係映射可以設置不同類型的鍵,使之很快能收集
arr
中不一樣的數據
** Set
數據結構,不允許出現重覆數據,而且 Set
支持解構 傳送門 **
const unique = arr => Array.from(new Set(arr));
// 或者通過 ES6 的 ...解構
const unique = arr => [...new Set(arr)];
簡單粗暴
** reduce
,給定初始值,根據數組迴圈給出最終值 **
const unique = (arr, result = []) => arr.reduce((prev,curr) => prev.includes(curr) ? prev : [...prev, curr], result);
三、總結
方法已經說了差不多了,就看你怎麼用了,其中有一些差不多的方法,只是給了說明,沒給具體的例子,希望大家自己去試一下,告辭!