最近在阅读了一些关于数组去重的文章,亲自比较了一些实现数组去重的思路
生成一个 distinct_array.js 文件;文件内容如下
1.数据准备(100000)
const testArr = (function () {
const arr = new Array(1000000);
for (let i = 0; i < arr.length; i += 1) {
arr[i] = Number((Math.random() * 10).toFixed());
}
return arr;
}());
console.log(`处理的数组长度${testArr.length}`);
2. 打印实验运算时间函数
function loggerDistinctTime(testArr, distinctFunction, distinctFunctionName) {
const start = Date.now();
const arr = distinctFunction(testArr);
const end = Date.now();
const takeUpTime = end - start;
console.log(`耗时:${takeUpTime} ${distinctFunctionName}, 去重后数组: ${arr}, 去重后数组长度${arr.length}`);
}
3.实现去重思路
3.1 ES5 语法实现
3.1.1 使用双重for循环
function distinctDoubleFor(arr) {
for (let i = 0; i < arr.length - 1; i += 1) {
for (let j = i + 1; j < arr.length; j += 1) {
if (arr[i] === arr[j]) {
arr.splice(j, 1);
j -= 1;
}
}
}
return arr;
}
3.1.2 使用filter和indexOf
function distinctEs5FilterAndIndexOf(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}
3.1.3 使用for 循环和indexOf
function distinctEs5IndexOfAndFor(arr) {
const distinctArr = [];
for (let i = 0; i < arr.length; i += 1) {
if (distinctArr.indexOf(arr[i]) === -1) {
distinctArr.push(arr[i]);
}
}
return distinctArr;
}
3.1.4 使用forEach循环和indexOf
function distinctEs5IndexOfAndForEach(arr) {
const distinctArr = [];
arr.forEach((item) => {
if (distinctArr.indexOf(item) === -1) {
distinctArr.push(item);
}
});
return distinctArr;
}
3.1.5 使用forEach循环和every
function distinctEs5ForEachAndEvery(arr) {
const distinctArr = [];
arr.forEach((item) => {
if (distinctArr.every(distinctArrItem => distinctArrItem !== item)) {
distinctArr.push(item);
}
});
return distinctArr;
}
3.1.6 使用for循环和every
function distinctEs5forAndEvery(arr) {
const distinctArr = [];
for (let i = 0; i < arr.length; i += 1) {
if (distinctArr.every(distinctArrItem => distinctArrItem !== arr[i])) {
distinctArr.push(arr[i]);
}
}
return distinctArr;
}
3.1.7 使用for循环和includes
function distinctEs5ForAndIncludes(arr) {
const distinctArr = [];
for (let i = 0; i < arr.length; i += 1) {
if (!distinctArr.includes(arr[i])) {
distinctArr.push(arr[i]);
}
}
return distinctArr;
}
3.1.8 使用forEach循环和includes
function distinctEs5ForEachAndIncludes(arr) {
const distinctArr = [];
arr.forEach((item) => {
if (!distinctArr.includes(item)) {
distinctArr.push(item);
}
});
return distinctArr;
}
3.2 ES6 语法实现
3.2.1 使用Set (前提数组元素为number类型)
function distinctEs6Set(arr) {
const distinctArr = new Set(arr);
return [...distinctArr];
}
3.2.2 使用for ... of 和结合obj的属性唯一的特性
function distinctEs6ForOfAndFor(arr) {
const distinctArr = [];
const distObject = {};
for (const item of arr) {
if (!distObject[item]) {
distinctArr.push(item);
distObject[item] = 'distinct';
}
}
return distinctArr;
}
3.3 使用先排序后去重数组的思路
3.3.1 使用sort加for循环剔除重复
3.3.3 使用冒泡排序和for循环剔除重复
以上两种本质上是三重for 循环,很傻的做法,故不展示实现
4. 执行函数得出去重时间
// es5 语法
loggerDistinctTime([...testArr], distinctDoubleFor, '双重循环去重');
loggerDistinctTime([...testArr], distinctEs5FilterAndIndexOf, 'es5filter和indexOf去重');
loggerDistinctTime([...testArr], distinctEs5IndexOfAndForEach, 'es5indexOf和forEach循环去重');
loggerDistinctTime([...testArr], distinctEs5IndexOfAndFor, 'es5indexOf和for循环去重');
loggerDistinctTime([...testArr], distinctEs5forAndEvery, 'es5every和for循环去重');
loggerDistinctTime([...testArr], distinctEs5ForEachAndEvery, 'es5every和forEach循环去重');
loggerDistinctTime([...testArr], distinctEs5ForAndIncludes, 'es5Includes和for循环去重');
loggerDistinctTime([...testArr], distinctEs5ForEachAndIncludes, 'es5Includes和forEach循环去重');
// es6 语法
loggerDistinctTime([...testArr], distinctEs6ForOfAndFor, 'es6forOf和obj去重');
loggerDistinctTime([...testArr], distinctEs6Set, 'es6Set去重');
如需查看该部分代码, 参考github地址: github.com/chendongfen…
5. 总结
5.1 for循环性能比forEach高,快两倍(你还会再使用forEach这个api吗)
5.2 使用obj的去重最快
5.3 for+ indexof/includes性能不相上下(为第二梯队)