·

JS实现数组去重的七种方法

发布时间:2024-08-28 23:24:49阅读量:205
专业文章
转载请注明来源

JS数组去重的方式

例:将下面数组去除重复元素(以多种数据类型为例)

const arr = [1, 2, 2, 'abc', 'abc', true, true, false, false, undefined, undefined, NaN, NaN]

1.利用Set()+Array.from()

Set对象:是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即Set中的元素是唯一的

Array.from() 方法:对一个类似数组可迭代对象创建一个新的,浅拷贝的数组实例。

const result = Array.from(new Set(arr))
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]

注意:以上去方式对NaNundefined类型去重也是有效的,是因为NaNundefined都可以被存储在Set中, NaN之间被视为相同的值(尽管在js中:NaN !== NaN)。

2.利用两层循环+数组的splice方法

通过两层循环对数组元素进行逐一比较,然后通过splice方法来删除重复的元素。此方法对NaN是无法进行去重的,因为进行比较时NaN !== NaN
function removeDuplicate(arr) {
  let 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-- // 保证j的值自加后不变
      }
    }
  }
  return arr
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]

3.利用数组的indexOf方法

新建一个空数组,遍历需要去重的数组,将数组元素存入新数组中,存放前判断数组中是否已经含有当前元素,没有则存入。此方法也无法对NaN去重。
  • indexOf() 方法:返回调用它的String对象中第一次出现的指定值的索引,从 fromIndex 处进行搜索。如果未找到该值,则返回 -1。
function removeDuplicate(arr) {
  const newArr = []
  arr.forEach(item => {
    if (newArr.indexOf(item) === -1) {
      newArr.push(item)
    }
  })
  return newArr // 返回一个新数组
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]

4.利用数组的includes方法

此方法逻辑与indexOf方法去重异曲同工,只是用includes方法来判断是否包含重复元素。
  • includes()方法:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
function removeDuplicate(arr) {
  const newArr = []
  arr.forEach(item => {
    if (!newArr.includes(item)) {
      newArr.push(item)
    }
  })
  return newArr
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]

注意:为什么includes能够检测到数组中包含NaN,其涉及到includes底层的实现。如下图为includes实现的部分代码,在进行判断是否包含某元素时会调用sameValueZero方法进行比较,如果为NaN,则会使用isNaN()进行转化。

具体实现可参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

简单测试includes()NaN的判断:

const testArr = [1, 'a', NaN]
console.log(testArr.includes(NaN)) // true

5.利用数组的filter()+indexOf()

filter方法会对满足条件的元素存放到一个新数组中,结合indexOf方法进行判断。
  • filter() 方法:会创建一个新数组,其包含通过所提供函数实现的测试的所有元素。
function removeDuplicate(arr) {
  return arr.filter((item, index) => {
    return arr.indexOf(item) === index
  })
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined ]

注意:这里的输出结果中不包含NaN,是因为indexOf()无法对NaN进行判断,即arr.indexOf(item) === index返回结果为false。测试如下:

const testArr = [1, 'a', NaN]
console.log(testArr.indexOf(NaN)) // -1

6.利用Map()

Map对象是JavaScript提供的一种数据结构,结构为键值对形式,将数组元素作为map的键存入,然后结合has()set()方法判断键是否重复。
  • Map 对象:用于保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值)都可以作为一个键或一个值。
function removeDuplicate(arr) {
  const map = new Map()
  const newArr = []

  arr.forEach(item => {
    if (!map.has(item)) { // has()用于判断map是否包为item的属性值
      map.set(item, true) // 使用set()将item设置到map中,并设置其属性值为true
      newArr.push(item)
    }
  })

  return newArr
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]

注意:使用Map()也可对NaN去重,原因是Map进行判断时认为NaN是与NaN相等的,剩下所有其它的值是根据 === 运算符的结果判断是否相等。

7.利用对象

其实现思想和Map()是差不多的,主要是利用了对象的属性名不可重复这一特性。
function removeDuplicate(arr) {
  const newArr = []
  const obj = {}

  arr.forEach(item => {
    if (!obj[item]) {
      newArr.push(item)
      obj[item] = true
    }
  })

  return newArr
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]


原文链接:https://blog.csdn.net/qq_52732369/article/details/121877897

0 人喜欢

评论区

暂无评论,来发布第一条评论吧!

弦圈热门内容

为什么可能没有体积的量子所组成的物质却有体积?

当你测量和观察周围的宇宙时,有一件事是可以肯定的:你看到、触摸到并以其他方式与之互动的物理对象都占据了一定的空间体积。无论是固体、液体、气体还是物质的任何其他形态,它都需要消耗能量来减少任何有形物质所占的体积。然而,看似矛盾的是,作为物质的基本成分,标准模型的粒子却根本没有可测量的体积;它们只是点粒子。那么,由无体积实体组成的物质如何占据空间,创造出我们所观察到的世界和宇宙呢?让我们从我们熟悉的事物开始,一步步分解,直到我们深入到支撑我们存在的量子规则。最后,我们可以从那里开始逐步向上。上图显示了对应于电磁波谱各个部分的尺寸、波长和温度/能量尺度。你必须使用更高的能量和更短的波长来探测最小的尺度。紫外线足以使原子电离,但随着宇宙的膨胀,光会系统地转移到更低的温度和更长的波长。如果你想了解体积,那么你必须了解我们测量物体大小的方式。确定宏观实体大小的方式通常是将其与已知大小的参考标准进行比较,例如尺子或其他测量棒。或者测量弹簧(或类似弹簧的物体)因该物体而位移的力、测量光穿过物体跨度所需的传播时间,甚至通过用特定波长的粒子或光子撞击物体的实验反馈来进行确定。正如光具有由其能量定义的量子力 ...

波尔兹曼大脑:宇宙中漂浮着至少7万5千亿亿亿个意识体

在这个广袤无垠的宇宙中,我们总爱幻想自己独一无二,是万物之灵。但你知道吗?根据某个奇妙的科学理论,你、我,甚至整个地球,可能都只是宇宙中随机“涨落”出来的一个意识体——没错,这就是让人脑洞大开的“玻尔兹曼大脑”假说!熵增定律:宇宙为何越来越“乱”?你的房间如果不打扫,是不是会越来越乱?这就是“熵增定律”在生活中的体现。简单来说,熵就是系统混乱程度的量度,而熵增定律则告诉我们,一个孤立系统的熵总是趋向于增加,直到达到最大化,也就是系统变得最混乱。宇宙,作为一个巨大的孤立系统,按理说也应该遵循这一法则。但奇怪的是,我们观测到的宇宙,似乎是从一个极其有序、熵极低的状态开始的。这,是为什么呢?玻尔兹曼的“脑洞”:宇宙其实是个“随机播放器”?这时,奥地利物理学家路德维希·玻尔兹曼登场了。他提出,熵增定律其实是统计性的,就像抛硬币,虽然正面朝上的概率是50%,但在无限次抛掷中,正面和反面出现的次数会趋于相等。同样,宇宙在大部分时间处于高熵态,但无限的时间尺度上,偶尔也会有“小概率事件”发生,即熵的随机涨落导致低熵态的出现。换句话说,我们现在所看到的这个有序、低熵的宇宙,可能只是一次“宇宙级”的随机 ...

Jürgen Jost黎曼几何与几何分析教材:Riemannian Geometry and Geometric Analysis

这本书是几何分析方面的入门教材,该教材先从最基本的黎曼流形讲起,然后逐步深入到李群和向量丛,接着到联络与曲率,基本上覆盖了几何分析很多重要的基础概念。这本书需要有一定的微分几何基础以及分析、李群等相关领域的基础,初学者谨慎使用。我高中的时候,就是对这本书的内容感兴趣,想要尝试理解,结果看到测地线就不懂了,接着后面看了点李群和向量丛就没再看了。建议先读Loring W Tu的两本微分几何教材Loring W Tu微分几何经典入门教材:An Introduction to Manifolds和Loring W Tu微分几何教材:Differential Geometry Connections, Curvature, and Characteristic Classes,有了一定的基础再专研Jürgen Jost的这本教材。我毕竟不是做微分几何的,所以关于这方面的就不说太多了。PS:作者不再提供附件下载。

Loring W Tu微分几何教材:Differential Geometry Connections, Curvature, and Characteristic Classes

在上帖Loring W Tu微分几何经典入门教材:An Introduction to Manifolds中,我提到高中时期,我为了看懂Jürgen Jost的几何分析教材Riemannian Geometry and Analysis,转而看Loring W Tu的An Introduction to Manifolds以及Differential Geometry Connections, Curvature, and Characteristic Classes。这本教材可以说是An Introduction to Manifolds的后续,建议先看一下An Introduction to Manifolds有了流形的基础,再看这本Connections, Curvature, and Characteristic Classes。本书开始就直接先从黎曼流形开始讲起,接着就讲曲率、联络这些微分几何进阶的重要基本概念。这也是为什么当初我会选择看这本书,因为这些内容刚好有助于我理解Riemannian Geometry and Analysis这本教材的内容(记得当时看到测地线就看不 ...

素数在整数整环中还是素的吗?

我的提问:一个整环$R$中的元素$p$是素的,如果$p$不是零或者一个单元,并且$p|ab$意味着$p|a$或者$p|b$(等价的$ab\in Rp$意味着$a \in Rp$或者$b\in Rp$)。一个整环$R$的元素$q$是不可约的,当$q$不是零或者一个单元,并且$q = ab$意味着$a$或$b$是一个单元。那么素数在整数整环中是素的吗?然后素数都是不可约的吗?回答1:这两个问题的都是对的。根据基础数论的事实,$\pm 1$是唯一可逆的整数,除$\pm 1$以外的整数可以唯一地表示为不同素数的乘积加上$\pm$,每个素数的幂都是正整数,这两个结果都很容易得到。回答2:素数在整数整环中既是素的,也是不可约的。根据定义,它们就是不可约的。为了证明它们是素的,请回顾一下欧几里得算法,该算法用于找到两个整数的GCD(并同时证明任意两个整数都有一个在等价意义下唯一的GCD,其中并不涉及素数的分解)。根据欧几里德算法可以得出,如果$d=\gcd(a,b)$对两个整数$a,b\in\mathbb Z$,则存在整数$u,v\in\mathbb Z$使得$d=ua+vb$。(贝祖特性。)现在, ...

2024-11-22凌晨:弦圈最近两周更新情况

在上篇弦圈11月10日上下更新计划:小金库、打赏等功能,我提到会更新网站多个功能。原本以为这些功能最多一周就能全部写完,结果当我真正开始写,才发现自己完全低估了这些功能实现的难度,以及所需要耗费的时间。而且由于我的完美主义倾向,导致我比原计划多开发了好几个功能,比如说编辑器插入公式、交易中心、收藏党最喜爱的收藏夹等。因为我想反正都大更新了,那干脆就更新得多一些,把以前埋的坑都填上。再然后支付功能比我想象中的要难得多,这不仅仅指代码难写,还包括支付宝的审核等问题,人事问题上也耗费了不少时间。在这里忍不住吐槽一下支付宝和微信支付,这国内两家巨头技术文档写的是真烂、真水。多少年了,支付宝支付SDK的demo示例还是Java、PHP,Python压根没写,只能自己摸索然后网上找到些零散的资料。微信支付先是需要微信认证强制每年收费300元,然后文档也是写得不清不楚。反正目前网站就暂时只支持支付宝吧,之后再把微信支付补上吧,因为真的被恶心到了。总之如今写了快两个星期了,这些功能终于要完成了,预计明后天就能上线测试。网站也完全没更新,也找不到人帮忙更新,只能先放着了。之后我会发一篇更新日志,更加详细 ...

弦圈11月10日上下更新计划:小金库、打赏等功能

这几天忙于写代码完善网站功能,不太有空更新文章和内容。因为弦圈没有借助任何建站工具和博客框架,是我自己前后端一起从零开始写的,因此开发得会比较慢,请谅解。。。目前计划上线功能首先就包括,前面弦圈更新日志:关于智力值和金币提到的小金库。获取金币的机制是:智力值存入银行(叫时空银行time bank?),然后根据日利率每天产生相应的金币。下图为测试画面其次为了让网站能够更好的运作下去,从而给大家提供更好的服务,我计划引入盈利功能。所谓盈利功能即是用户通过弦圈来获得收益的相关功能,包括打赏功能、接广告功能、接悬赏功能。这些功能主要是为了鼓励大家为社区做贡献,并且让需要得到帮助的人更容易获得帮助(毕竟大佬们忙得很,不会轻易帮助你解决问题)。具体规则暂定如下:想要让弦圈的用户能赚钱,那弦圈必须自己先能赚到钱,目前我计划引入弦圈广告和用户交易中心。至于弦圈广告,我打算采用信息流广告、侧边栏广告、文章内嵌广告,拒绝弹窗之类遮蔽视线的广告,因此不会影响用户体验。最后我还得把之前留的坑——创作中心给填上,就是一个给创作者的方便管理内容、查看数据的模块。测试画面如下:尽情期待😇

Grothendieck经典著作:代数几何原理EGA 1(1971第二版)法语+英译

在前面几贴中,我已经分别分享了Grothendieck的代数几何三部曲EGA、SGA、FGA,链接如下:代数几何教皇Grothendieck经典著作:代数几何原理EGA法语原版全系列(1)代数几何教皇Grothendieck经典著作:代数几何讨论班SGA法语原版全系列代数几何教皇Grothendieck经典著作:代数几何基础FGA法语原版+英文译版但其实EGA 1还有1971年的第二版,Grothendieck在EGA 1第二版中更新了一些内容,因此一些概念定义会与第一版中有出入。原本我也是不太知道EGA竟然还会有第二版,直到后来有次看文献时,发现作者引用了EGA 1(1971)才知道有这一版本。对比EGA 1第一版跟第二版,感觉第二版要比第一版更好读一些,似乎思路行文更清晰,也更好理解。并且值得开心的是,EGA 1第二版有完整英译,现在我全都分享出来。更新:作者不再提供文件下载。