您现在的位置是:网站首页> 编程资料编程资料

JavaScript常用数组去重的方法及对比详解_javascript技巧_

2023-05-24 347人已围观

简介 JavaScript常用数组去重的方法及对比详解_javascript技巧_

前言

数组去重在面试和工作中都是比较容易见到的问题。

这篇文章主要是来测试多个方法,对下面这个数组的去重结果进行分析讨论。如果有不对的地方,还请大家指出。

 const arr = [ 1, 1, "1", "1", 0, 0, "0", "0", true, false, "true", "false", "a", "A", undefined, undefined, "undefined", null, null, 'null', NaN, NaN, +0, -0, new String("1"), new String("1"), Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], [] ]; 

特殊类型

console.log(1 == "1"); // true console.log(1 === "1"); // false console.log(0 == "0"); // true console.log(0 === "0"); // false console.log(0 == +0); // true console.log(0 === +0); // true console.log(0 == -0); // true console.log(0 === -0); // true console.log(+0 == -0); // true console.log(+0 === -0); // true console.log(0 == false); // true console.log(0 === false); // false console.log(0 == undefined); // false console.log(0 === undefined); // false console.log(0 == null); // false console.log(0 === null); // false console.log(1 == true); // true console.log(1 === true); // false console.log(undefined == null); // true console.log(undefined === null); // false console.log(NaN == NaN); // false console.log(NaN === NaN); // false console.log(new String("1") == new String("1")); // false console.log(new String("1") === new String("1")); // false Object.prototype.toString.call(new String('1')) // '[object String]' console.log(/a/ == /a/); // false console.log(/a/ === /a/); // false Object.prototype.toString.call(/a/); //'[object RegExp]' console.log(Symbol(1) == Symbol(1)); // false console.log(Symbol(1) === Symbol(1)); // false console.log({} == {}); // false console.log({} === {}); // false console.log([] == []); // false console.log([] === []); // false 

接下来,我们看看下面多个去重方法,对以上特殊类型的去重效果。

代码一(暴力解法)

// 暴力解法一 function unique(array) { if (!Array.isArray(array)) { console.log("type error!"); return; } const res = [array[0]]; let arrLen = array.length; let resLen = res.length; for (let i = 0; i < arrLen; i++) { let flag = true; for (let j = 0; j < resLen; j++) { if (array[i] === res[j]) { flag = false; break; } } if (flag) { res.push(array[i]); resLen = res.length; } } return res; } // [1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', NaN, NaN, String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []] 

输出:

[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', NaN, NaN, String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []]

输出结果说明:

  • 去重+0-00
  • NaN不去重
  • 对象new String("1")/a/{}不去重
  • 数组[]不去重
  • Symbol(1)不去重

暴力解法,简单易理解,兼容性好。去重结果如上所示。

代码二(ES6)

// ES6 Array.from + Set 方法一 function unique(array) { if (!Array.isArray(array)) { console.log('type error!') return } return Array.from(new Set(array)) } // ES6 点运算 + Set 方法二 function unique1(array) { if (!Array.isArray(array)) { console.log('type error!') return } return [...new Set(arr)] } // ES6 箭头函数 + 点运算 + Set 方法三 const unique2 = (array) => { if (!Array.isArray(array)) { console.log('type error!') return } return [...new Set(arr)] } // ES6 Map + ES5 filter 方法四 function unique3(array) { if (!Array.isArray(array)) { console.log('type error!') return } const seen = new Map() return array.filter((a) => !seen.has(a) && seen.set(a, 1)) } 

输出:

[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', NaN, String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []]

输出结果说明:

  • 去重+0-00
  • 去重NaN
  • 对象new String("1")/a/{}不去重
  • 数组[]不去重
  • Symbol(1)不去重

代码三(indexOf + forEach)

利用indexOf检测元素在新数组是否存在

// indexOf + forEach 利用indexOf检测元素在新数组是否存在 function unique(array) { if (!Array.isArray(array)) { console.log('type error!') return } const newArr = []; array.forEach((el) => { if (newArr.indexOf(el) === -1) { newArr.push(el); } }); return newArr; } 

输出:

[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', NaN, NaN, String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []]

输出结果说明:

  • 去重+0-00
  • NaN不去重
  • 对象new String("1")/a/{}不去重
  • 数组[]不去重
  • Symbol(1)不去重

代码四(indexOf + filter)

利用indexOf检测元素在数组中第一次出现的位置是否和元素现在的位置相等

// indexOf + forEach 利用indexOf检测元素在新数组是否存在 function unique(array) { if (!Array.isArray(array)) { console.log('type error!') return } return array.filter((item, index) => { return array.indexOf(item) === index; }); } console.log([NaN].indexOf(NaN)); // -1 

输出:

[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []]

输出结果说明:

  • 去重+0-00
  • 两个NaN都会被删除
  • 对象new String("1")/a/{}不去重
  • 数组[]不去重
  • Symbol(1)不去重

重点:

console.log([NaN].indexOf(NaN)); // -1 

代码五(sort排序,不支持Symbol)

sort()方法主要是用于对数组进行排序,默认情况下该方法是将数组元素转换成字符串,然后按照ASC码进行排序

// sort()方法不支持Symbol,Symbol不支持转换成字符串 function unique(array) { if (!Array.isArray(array)) { console.log("type error!"); return; } const sortArr = array.sort(); const newArr = []; sortArr.forEach((el, i) => { if (sortArr[i] !== sortArr[i - 1]) { newArr.push(el); } }); return newArr; } 

输出:

[[], [], /a/, /a/, 0, "0", 0, 1, "1", String {'1'}, String {'1'}, "A", NaN, NaN, {}, {}, "a", false, "false", null, "null", true, "true", "undefined", undefined]

输出结果说明:

  • +0-00"0"位置不同会导致去重不了
  • NaN不去重
  • 对象new String("1")/a/{}不去重
  • 数组[]不去重
  • sort()方法不支持处理含有Symbol的数组

代码六(includes)

利用includes()方法检查新数组是否包含原数组的每一项

// 利用includes()方法检查新数组是否包含原数组的每一项 function unique(array) { if (!Array.isArray(array)) { console.log("type error!"); return; } const newArr = []; array.forEach((el) => { newArr.includes(el) ? newArr : newArr.push(el); }); return newArr; } 

输出:

[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', NaN, String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []]

输出结果说明:

  • 去重+0-00
  • 去重NaN
  • 对象new String("1")/a/{}不去重
  • 数组[]不去重
  • Symbol不去重

代码七(includes+reduce)

利用includes()方法检查新数组是否包含原数组的每一项

// 利用includes()方法检查新数组是否包含原数组的每一项 function unique(array) { if (!Array.isArray(array)) { console.log("type error!"); return; } return array.reduce((pre, cur) => { !pre.includes(cur) && pre.push(cur); return pre; }, []); } 

输出:

[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', NaN, String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []]

输出结果说明:

  • 去重+0-00
  • 去重NaN
  • 对象new String("1")/a/{}不去重
  • 数组[]不去重
  • Symbol不去重

代码八(对象key)<

-六神源码网