js數(shù)組去重解決辦法
js數(shù)組去重是前端面試中經(jīng)常被問的題目,考察了面試者對js的掌握,解決問題的思路,以及是否具有專研精神。曾經(jīng)一位前端界大神告訴我,解決問題的方式有很多種,解決問題時多問問自己還有沒有其他的方法,探求最優(yōu)解決方案才能學(xué)到更多。
方案一
/**
* 1.構(gòu)建一個新數(shù)組
* 2.遍歷目標(biāo)數(shù)組,依次取出每一個元素
* 3.將取出的元素與新數(shù)組里面的所有元素進行比較,
* 如果沒有出現(xiàn) -> 該元素添加到新數(shù)組中,
* 如果出現(xiàn) -> 處理下一個目標(biāo)數(shù)組元素
* */
function distinct(arr) {
console.time(); //跟蹤方法的占用時長
var result = []; // 構(gòu)建結(jié)果數(shù)組result
for (var i = 0, len = arr.length; i < len; i++) {
for (var j = 0, rlen = result.length; j <= rlen; j++) {
if (arr[i] === result[j]) {
break;
}
if (j == result.length) {
result.push(arr[i]);
}
}
}
console.timeEnd();
return result;
}
方案優(yōu)點:
- 結(jié)果數(shù)組與目標(biāo)數(shù)組的順序保持一致
- 思路簡單,兼容性好
方案缺點:
- 速度慢
方案二
/**
*1.目標(biāo)數(shù)組排序
*2.遍歷目標(biāo)數(shù)組,檢測數(shù)組中的第i 個元素與結(jié)果數(shù)組中最后一個元素是否相同,如果不同,則將該元素添加到結(jié)果數(shù)組中
* */
function distinct(arr) {
console.time();
var result = [];
arr = arr.sort();
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i] !== result[result.length - 1]) {
result.push(arr[i])
}
}
console.timeEnd();
return result;
}
方案優(yōu)點:
- 方案中先排序,后遍歷,速度比方法一快
方案缺點:
- 方案中使用了數(shù)組排序sort,打亂了原有順序
Tips:數(shù)組排序
js中提供了數(shù)組排序方法sort,使用時需要注意以下幾點:
- 調(diào)用sort方法時改變了目標(biāo)數(shù)組本身,非生成新數(shù)組
- sort方法默認按照字符順序進行排序,不過提供了回調(diào)方法,可以自定義排序規(guī)則
現(xiàn)有一數(shù)組arr:1,11,23,56,3,4,5,7,562,67
按字符排序
arr.sort() // 1, 11, 23, 3, 4, 5, 56, 562, 67, 7
按數(shù)字大?。赫?/h5>
arr.sort((a,b) => a-b) // 1, 3, 4, 5, 7, 11, 23, 56, 67, 562
按數(shù)字大?。旱剐?/h5>
arr.sort((a,b) => b-a) // 562, 67, 56, 23, 11, 7, 5, 4, 3, 1
方案三
/**
* 利用ES6的 數(shù)據(jù)結(jié)構(gòu)SET的無重復(fù)值特性
* Array.from 將類數(shù)組轉(zhuǎn)換成數(shù)組
* */
function distinct3(arr) {
console.time();
var result = Array.from(new Set(arr));
console.timeEnd();
return result;
}
方案優(yōu)點:
-
代碼簡潔,執(zhí)行速度快
方案缺點:
-
ES6語法,使用時需要考慮兼容性問題
方案四
/**
* 利用對象屬性無重復(fù)的特點
* 遍歷目標(biāo)數(shù)組,將值設(shè)置為對象屬性
* Object.keys 將對象的所有屬性提取成一個數(shù)組
* */
function distinct(arr) {
console.time();
var result = {};
for (var i = 0, len = arr.length; i < len; i++) {
result[arr[i]] = '';
}
result = Object.keys(result);
console.timeEnd();
return result;
}
方案優(yōu)點:
-
速度快
方案缺點:
-
1 與 '1' 無法區(qū)分
-
結(jié)果數(shù)組中的值全部為字符串
-
占內(nèi)存,相當(dāng)于利用空間換時間
方案五
/**
* Array.filter 數(shù)組過濾函數(shù),只保留符合條件的值
* indexOf 查找元素第一次出現(xiàn)的位置,所有第1次之后查找的元素位置都不符合條件
* */
function distinct(arr) {
console.time();
var result = arr.filter(function (elem, index, self) {
return self.indexOf(elem) === index;
});
console.timeEnd();
return result;
}
測試
隨機生成包含10000個數(shù)字的數(shù)組
function random() {
var a = [];
for (var i = 0; i < 10000; i++) {
a.push(Math.ceil(i * Math.random()))
}
return a;
}
arr.sort((a,b) => a-b) // 1, 3, 4, 5, 7, 11, 23, 56, 67, 562
arr.sort((a,b) => b-a) // 562, 67, 56, 23, 11, 7, 5, 4, 3, 1
方案三
/**
* 利用ES6的 數(shù)據(jù)結(jié)構(gòu)SET的無重復(fù)值特性
* Array.from 將類數(shù)組轉(zhuǎn)換成數(shù)組
* */
function distinct3(arr) {
console.time();
var result = Array.from(new Set(arr));
console.timeEnd();
return result;
}
方案優(yōu)點:
- 代碼簡潔,執(zhí)行速度快
方案缺點:
- ES6語法,使用時需要考慮兼容性問題
方案四
/**
* 利用對象屬性無重復(fù)的特點
* 遍歷目標(biāo)數(shù)組,將值設(shè)置為對象屬性
* Object.keys 將對象的所有屬性提取成一個數(shù)組
* */
function distinct(arr) {
console.time();
var result = {};
for (var i = 0, len = arr.length; i < len; i++) {
result[arr[i]] = '';
}
result = Object.keys(result);
console.timeEnd();
return result;
}
方案優(yōu)點:
- 速度快
方案缺點:
- 1 與 '1' 無法區(qū)分
- 結(jié)果數(shù)組中的值全部為字符串
- 占內(nèi)存,相當(dāng)于利用空間換時間
方案五
/**
* Array.filter 數(shù)組過濾函數(shù),只保留符合條件的值
* indexOf 查找元素第一次出現(xiàn)的位置,所有第1次之后查找的元素位置都不符合條件
* */
function distinct(arr) {
console.time();
var result = arr.filter(function (elem, index, self) {
return self.indexOf(elem) === index;
});
console.timeEnd();
return result;
}
測試
隨機生成包含10000個數(shù)字的數(shù)組
function random() {
var a = [];
for (var i = 0; i < 10000; i++) {
a.push(Math.ceil(i * Math.random()))
}
return a;
}
現(xiàn)在執(zhí)行上述去重方法,取5次測試結(jié)果的平均值:
| 方法一 | 方法二 | 方法三 | 方法四 | 方法五 | |
|---|---|---|---|---|---|
| 第一次 | 91.281 | 7.921 | 4.36 | 2.038 | 68.856 |
| 第二次 | 104.492 | 7.519 | 2.267 | 1.328 | 70.555 |
| 第三次 | 105.937 | 8.874 | 1.804 | 1.680 | 73.020 |
| 第四次 | 100.524 | 5.287 | 2.602 | 1.573 | 85.129 |
| 第五次 | 106.612 | 8.990 | 1.615 | 1.963 | 79.115 |
| 平均 | 101.769 | 7.718 | 2.529 | 1.716 | 75.335 |
從執(zhí)行速度來看,方法四 < 方法三 < 方法二 < 方法五 < 方法一
方法四最快,方法一最慢。但是五種方法各有優(yōu)缺點,使用時要根據(jù)實際情況選擇適合的方案。

