广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >JavaScript常用数组去重的方法及对比详解
  • 623
分享到

JavaScript常用数组去重的方法及对比详解

2024-04-02 19:04:59 623人浏览 安东尼
摘要

目录前言特殊类型代码一(暴力解法)代码二(es6)代码三(indexOf + forEach)代码四(indexOf + filter)代码五(sort排序,不支持Symbol)代码

前言

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

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

 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)

利用了对象的key不可以重复的特性来进行去重

// 利用了对象的key不可以重复的特性来进行去重
function unique(array) {
    if (!Array.isArray(array)) {
      console.log("type error!");
      return;
    }
    
    const obj = {};
    const newArr = [];
    array.forEach((val) => {
      if (!obj[typeof val + JSON.stringify(val)]) {
        // 将对象序列化之后作为key来使用
        obj[typeof val + jsON.stringify(val)] = 1;
        newArr.push(val);
      }
    });
    return newArr;
}

输出:

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

输出结果说明:

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

将不该去重的Symbol去重了;将两个/a/全部删除了

总结

方法结果说明
for循环暴力解法[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.去重+0、-0、0;
2.NaN不去重;
3.对象new String("1")、/a/、{}不去重;
4.数组[]不去重;
5.Symbol(1)不去重;
ES6解法[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/, [], []1.去重+0、-0、0;
2.去重NaN;
3.对象new String("1")、/a/、{}不去重;
4.数组[]不去重;
5.Symbol(1)不去重;
indexOf + forEach[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.去重+0、-0、0;
2.NaN不去重;
3.对象new String("1")、/a/、{}不去重;
4.数组[]不去重;
5.Symbol(1)不去重;
indexOf + filter[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', String {'1'}, String {'1'}, Symbol(1), Symbol(1), {}, {}, /a/, /a/, [], []]1.去重+0、-0、0;
2.两个NaN都会被删除;
3.对象new String("1")、/a/、{}不去重;
4.数组[]不去重;
5.Symbol(1)不去重;
sort排序,不支持Symbol[[], [], /a/, /a/, 0, "0", 0, 1, "1", String {'1'}, String {'1'}, "A", NaN, NaN, {}, {}, "a", false, "false", null, "null", true, "true", "undefined", undefined]1.+0、-0、0、"0"位置不同会导致去重不了
2.NaN不去重;
3.对象new String("1")、/a/、{}不去重;
4.数组[]不去重;
5.sort()方法不支持处理含有Symbol的数组;
includes[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/, [], []]1.去重+0、-0、0;
2.去重NaN;
3.对象new String("1")、/a/、{}不去重;
4.数组[]不去重;
5.Symbol(1)不去重;
includes+reduce[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/, [], []]1.去重+0、-0、0;
2.去重NaN;
3.对象new String("1")、/a/、{}不去重;
4.数组[]不去重;
5.Symbol(1)不去重;
对象key[1, '1', 0, '0', true, false, 'true', 'false', 'a', 'A', undefined, 'undefined', null, 'null', NaN, String {'1'}, Symbol(1), {}, []]1.去重+0、-0、0;
2.去重NaN;
3.去重对象new String("1")、{};两个/a/全部被删除了;
4.去重数组[];5.去重Symbol

上面只是简单结果的去重总结,具体的去重选择还需要根据我们业务场景来选择去重方法。

演示地址

可以去GitHub仓库查看演示代码

到此这篇关于javascript常用数组去重的方法及对比详解的文章就介绍到这了,更多相关JavaScript数组去重内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: JavaScript常用数组去重的方法及对比详解

本文链接: https://www.lsjlt.com/news/164806.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript常用数组去重的方法及对比详解
    目录前言特殊类型代码一(暴力解法)代码二(ES6)代码三(indexOf + forEach)代码四(indexOf + filter)代码五(sort排序,不支持Symbol)代码...
    99+
    2022-11-13
  • JavaScript中数组去重常用的五种方法详解
    目录1.对象属性(indexof)2.new Set(数组)3.new Map()4.filter() + indexof5.reduce() + includes补充原数组 con...
    99+
    2022-11-13
  • JavaScript常用数组去重方法
    本篇内容主要讲解“JavaScript常用数组去重方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript常用数组去重方法”吧!数组去重,一般都是在面试的时候才会碰到,一般是要求手...
    99+
    2023-06-20
  • JS对象数组去重的3种方法示例及对比
    目录一.去重前后数据对比二.使用方法1.使用filter和Map2.使用reduce3.使用for循环三.2400条数据,三种方法处理时间对比总结一.去重前后数据对比 // 原数...
    99+
    2022-11-12
  • Javascript数组去重的几种方法详解
    目录数组去重1 双层for循环(类似冒泡排序的双层循环写法)2 循环和indexof、循环和includes3 利用对象属性不能重复去重4 ES6 Set5 ES6 Array. p...
    99+
    2022-11-12
  • JavaScript数组去重的几种方法详谈
    目录一、Set去重二、双重for循环去重三、利用indexOf去重四、利用icludes去重五、filter六、Map总结一、Set去重 function funSet(arr...
    99+
    2022-11-12
  • 使用JavaScript对数组去重的方法有哪些
    这篇文章将为大家详细讲解有关使用JavaScript对数组去重的方法有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. 利用对象的 key 唯一众所周知,对象的key不可重复,否则后者...
    99+
    2023-06-14
  • javascript中数组去重常用方法有哪些
    这篇文章将为大家详细讲解有关javascript中数组去重常用方法有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体如下:数组去除重复值是面试常考内容,也是很容易用...
    99+
    2022-10-19
  • 详解JavaScript数组的常用方法
    目录数组的常用方法pop()unshift()shift()slice()splice()数组元素去重concat()join()reverse()sort()总...
    99+
    2022-11-12
  • JavaScript实现数组对象去重的多种方法
    目录JavaScript实现数组对象去重的多种方法一、使用 Set 对象:二、使用`reduce`方法:三、使用`filter`方法补充:js数组对象去重1、使用reduce()方法...
    99+
    2023-02-10
    js数组对象去重 js数组去重
  • 关于JavaScript数组对象去重的几种方法
    数组对象如下: let repeatData = [ { id: 1, name: 'sun', age: 18 }, { id: 1, name: ...
    99+
    2023-05-17
    JavaScript数组去重 js数组对象去重
  • JS数组去重的常用4种方法
    1.ES6的Set类数组去重 var arr = [1,2,2,3,3,4,4,1,5,6,6,5] function unique (arr) { return Array.f...
    99+
    2022-11-13
  • Swift 数组及常用方法详解总结
    目录1. 创建数组2. 快捷创建重复元素的数组3. 数组相加4. 常用方法5. 数组遍历Swift 数组及常用方法 1. 创建数组 // 创建整型数组 var array1: [...
    99+
    2022-11-12
  • JavaScript数组常用方法解析及数组扁平化
    目录前言一、常用数组操作方法push末尾追加元素pop删除数组末尾元素sort排序shift数组开头添加元素 && unshift数组开头删除元素数组合并concat...
    99+
    2022-11-13
  • javascript利用set进行数组去重的方法是什么
    这篇文章主要介绍“javascript利用set进行数组去重的方法是什么”,在日常操作中,相信很多人在javascript利用set进行数组去重的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用...
    99+
    2022-10-19
  • Java中对象数组的使用方法详解
    在Java中,对象数组是一种特殊类型的数组,可以存储任意类型的对象。以下是关于Java对象数组的使用方法的详细解释:1. 声明对象数...
    99+
    2023-08-15
    Java
  • JavaScript常用数组元素搜索或过滤的四种方法详解
    目录Array.filter()Array.find()Array.includes()Array.indexOf()结语获取满足特定条件的数组中的所有项目要检查是否满足条件?检查数...
    99+
    2022-11-13
  • Django中常用的查询数据方法及查询对象的条件详解
    (1)常用的查询方法: 1.获取所有记录: s = User.objects.all() 2.获取第一条数据: s = User.objects.first() 3...
    99+
    2022-11-12
  • JavaScript中遍历数组和对象有哪些常用的方法
    这篇文章主要介绍“JavaScript中遍历数组和对象有哪些常用的方法”,在日常操作中,相信很多人在JavaScript中遍历数组和对象有哪些常用的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操...
    99+
    2022-10-19
  • 关于多线程常用方法以及对锁的控制(详解)
    1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是如果有Synchronized同步块,其他线程仍然不同访问共享数据。注意该方法要捕获异常比如有两个线程同时执行(没有S...
    99+
    2023-05-31
    多线程 控制
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作