·

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

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

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 人喜欢

评论区

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

弦圈热门内容

Charles Rezk拓扑学notes:Compactly Generated Spaces

本notes主要讲的是拓扑学中$k$-spaces与$k$-Hausdorff space的相关概念,之所以保存这份notes是因为我当初学习高阶范畴的时候,刚好需要用到这些概念。比如说,无穷范畴的定义就需要用到他们:A topological category is a category which is enriched over $\mathcal{C}\mathcal{G}$, the category of compactly generated (and weakly Hausdorff) topological spaces. The category of topological categories will be denoted by $\mathcal{C}at_{top}$.而抛开它与无穷范畴的联系,仅仅考虑它在拓扑学本身的意义,我觉得这也是本拓扑学方面有趣的notes,不仅是因为有趣的概念如$k$-空间、$k$-豪斯多夫空间,还有紧致生成的空间,还包括一些有趣的结论。总之,对高阶范畴、或者更深入的拓扑学感兴趣的人,可以看看。

点集拓扑求救

以及有没有推荐的点集拓扑教材

我翻译了Wiki、nLab、Stack Project的部分条目,以及一些教材中的定义,全放到了数学百科中

一两个月前,网站浏览人数比较少的时候,我也比较空闲,因此花了一些时间翻译了国外Wiki、nLab、Stack Project的部分条目,同时,我还将一些教材中的定义以及少部分自己写的英文notes中的定义翻译成了中文。然后我将这些翻译好的内容全都放进了数学百科中。现在因为新建了好几个子圈子,我也陆续将这些词条分门别类放进了不同的子圈。我之所以会翻译这些东西,一来是因为中文互联网的数学资源属实是过于稀缺了,每个学数学的人想要更好的发展都离不开英语这一关。但是总有人对数学感兴趣却英语不好,这也意味着有一部分人会欣赏不了英文的一些美妙的数学。二是因为词条是可以插入到文章里的,这会方便看文章的人快速查看相关术语的意思,所以在弦圈里多放些词条不仅有利于网站内容更丰富,而且能让学习交流变得更加顺畅。下面我整理一下我具体翻译了哪些词条,其实也不是很多。主要问题是翻译数学内容本身并不耗时间,真正耗时间的是输入Latex代码😅,即便我写数学好几年了,Latex也早就熟练运用,但我还是感觉在写数学的过程中Latex的输入占用了过多时间。层预层局部赋环空间赋环空间概形凸秩$p$-可除群函数向量向量空间反同态 ...

陈省身微分几何经典教材《微分几何讲义》

一说到陈省身经典的微分几何教材《微分几何讲义》,就勾起我很多回忆。这本书是我初三时期入门微分几何的教材,虽然相比于Loring W Tu微分几何经典入门教材:An Introduction to Manifolds的教材没那么好理解,但是却比王幼宁的《微分几何讲义》更加的友好。我当时真的挺喜欢陈省身的教材的,虽然以我如今的水平看,当时的我并没有真正的看懂这本书,但这是我微分几何的启蒙书。我人生中看的第一本微分几何的书是王幼宁的《微分几何讲义》,但是我虽然很有兴趣,但却没能读下去,因为开篇就直接看不懂。而陈省身的《微分几何讲义》至少我能读下去,不至于开篇就直接来那么难的东西,我也是靠这本教材知道了很多微分几何的重要概念。我到高一还在看陈省身这本教材,直到后来高二为了读懂Jürgen Jost黎曼几何与几何分析教材:Riemannian Geometry and Geometric Analysis,我不得不看自己当时嫌弃的Loring W Tu的An Introduction to Manifolds,才打开了新世界,原来还是这么好看的微分几何入门教材,Loring W Tu的书确实比陈 ...

初中生如何自学数学?

知乎提问:我想这样子自学数学?纯兴趣爱好。我想从高中数学开始自学,用教材帮这本教辅书自学。然后学完高中后整理一下初等数学的知识。是不是就可以开始自学高数了?现在我打开高数好多证明题和不等式都不会做。然后把高等数学,数学分析,线性代数,高等代数,概率论与数理统计,复变函数与积分变换,实分析,复分析,泛函分析,抽象代数,代数几何,长微分方程,偏微分方程,微分几何都学完。大致就是这样的人生规划,初等数学学透了是不是就可以理解学习高等数学了?我的回答:我觉得按部就班的按顺序学习没多大意思,我初三的时候是先把导数、积分这些高中最难但却是微积分最基本的概念“学懂”,然后才学别的比较基础的概念如集合。原因无它,就是因为当时这些更感兴趣。因此与其纠结于把什么学透了再来理解什么,不如换成先尝试理解什么,理解不了再来理解什么。我初三的时候除了学会了导数、积分、加速度这些高中数学、物理的概念,但也没太过深入。顶多再学了个正余弦定理拿来应付中考。我从初中开始养成的习惯就是,对什么感兴趣就直接学它,学不懂再看其他的,因此我初中的时候还直接学了范畴的定义(只是看懂了表面的定义)。直到初三升高一的假期,我才买了高中 ...

失业、分配不平衡和结构性转变:人还能否“卷”过AI

白果/文 人类对AI,尤其是AI冲击社会就业与收入分配的担忧,其实由来已久。20世纪70年代至今,我们至少经历过三波AI发展的大潮。当一轮轮潮水退去,人们发现人工智能似乎并没有想象的那么厉害,不禁有了更自信乐观的理由。然而,这一轮AI的发展速度和能力似乎不可同日而语。ChatGPT(Generative Pre-Trained Transformer)及各种生成式AI工具的出现,使人类可以用自然语言的方式给计算机发出指令,这在很大程度上打破了某些专业壁垒。虽然当前AI生成内容在准确度、独创性上还有待提高,但替代人工、降本增效的能力显而易见。那么,此轮AI发展将冲击哪些职业,又是否会如乐观者期待的那样,带来大量新的工作?在尝试回答这两个备受关注的问题之外,笔者也试图分析AI带来的社会结构性转变,以及为了应对这些转变,个体和社会应作出怎样的努力。我们看到,目前AI工具的发展,可能会导致技术性失业、收入分配结构的恶化尤其是“极化”效应,加剧各种社会问题。而要想让技术进步更好地实现普惠价值,我们需对现有制度进行深入反思,尝试对社会系统进行革新和再设计。归根结底,技术的社会价值实现和进步方向最终 ...

叔本华:人类是一步一步地迈向死亡的存在物

丹麦哲学家齐克果(Sren Kierkegaard)说:「什么是诗人?一个不快乐的人:他把深层的痛苦埋在心里;但他的唇舌是如此形塑,以致从中经过的叹息和哀嚎,都成了动人的乐章。」诗人好像真的是比较不快乐。在一个诗人选择自杀后,我们一般都对之予以同情和理解,彷彿诗人们自我了结生命是可以谅解的。种种的思绪,不禁令人想起德国哲学家叔本华(Arthur Schopenhauer)对艺术和自杀的一些想法。叔本华向来以所谓悲观主义哲学闻名,不少没读过他的人也大概知道这点。所谓悲观主义,是一种以负面的角度去理解价值的方案。而所谓负面,又有几个面向。首先,叔本华说,人类是一步一步地迈向死亡的存在物,从这个存在特质去看,人类的存在目标和目的也就指向着死亡。「假如存在的目标是死亡,那为什么不能现在就死?」一位诗人或许正在如此提问。还不能马上就死。正因为人是「步向死亡」的存有者,人的存在处境便是动态的──就于现在的每一刻。因此,「现在」便有了独特的价值。就如他在《作为意志和表象的世界》(The World as Will and Representation)第一册中解释:真正的存在就只在现在。现在一直往过 ...

哲学家叔本华的《生存空虚说》

叔本华虽然是悲观主义者,但他的哲学思想很是值得现代人思索。作为哲学家的叔本华反对基督教并认为基督教教义虚伪,其真理是为受苦,叔本华思想深受印度教与佛教影响深远。但就基督徒而言会同意人生是苦,但非是受苦。有时悲观不一定会带来负向的思考,其实悲观者的心思较为细腻而敏感,对生活的体验也较深刻;悲观只不过是一种思想,一种观念。「人生是一种迷误。因为人的欲望是很复杂的也不容易满足,即使当时得到满足,那也只是一时的状态,很快的人又会有更多的烦恼」。——叔本华《生存空虚说》当人对于人生所要求多时就会很容易不快乐、不满足,而想要生活快乐实在很难,几乎不可能,能切切实实的明白这番道理,对人生的欲求就会减少。世界的脚步不停的在变,是一种持续性的历程,世界也绝不会因你而改变,它仍然无情的转动着。在生存空虚一文中:「人一生所追求的只是想象中的幸福。」事实上叔本华以一种虚无的论调,来思辨他对人生的看法,但有时想想,确是如同他所表述;人的欲望无穷大,当人类对人生开始想追求一切时,欲望就开始无法满足人心。在文中作者认为,当人认为生命是为了活下去,生命自然就有价值;但若是有其目标,就只是昙花一现般,最终还是等于无;也 ...

GTM242 Grillet抽象代数经典教材:Abstract Algebra 2nd

本次我分享的教材是GTM242——Abstract Algebra,作者是Pierre Antoine Grillet。本教材是我高中时期最中意的抽象代数教材了😄,当时的我看过好几本抽象代数的教材,包括国内的某本抽象代数小册子教材(已经找不到了,不知道扔哪了,记得封面是黄黑色的),最后还是GTM242让我真正学会了抽象代数。高中的时候我基本每天回家的路上都会看它,并且最后我还把它的纸质书从国外亚马逊买回来了。这本教材我个人感觉通俗易懂,挺适合喜欢代数的初学者。整本书先从最基本的二元运算讲到半群,接着才到更加抽象的群的概念。教材的整体节奏也是循序渐进,先群论接着环论,之后才是域论。讲完前面的基础概念后,才开始更加深入的话题,如伽罗华理论。本书内容可以说十分完备,而且例子也丰富,带有趣的配套习题。此书不仅可以用于学习抽象代数,还能用于学习交换代数和同调代数,完备得有些出乎意料,感觉把所有代数的重要基础概念都囊括其中。应该可以跟Serge Lang的Algebra相提并论。值得一提的是,Serge Lang的Algebra经常被推荐用于作为代数方面的词典,用于遇到不懂或者少见的代数概念时去查 ...

Atiyah:Commutative Algebra使用攻略

刷题刷傻了~这次是交换代数的经典教材,M.F.Atiyah,I.G.MacDonald的Introduction to Commutative Algebra,以下简称A&amp;M。A&amp;M在知乎上也很有声誉,基本是公认的交换代数入门书。A&amp;M很薄,128页,我大概读了二十余天,习题全部刷完了,觉得相当有收获。难度有,但并没有想象中的大,我完全能接受。A&amp;M几乎绝版了,不过可以去专门进口书店买到,打印也不失为一个好选择。说起来我本来打算把交换代数放在明年再读的,但恰逢我校大二同学开展了一个交换代数讨论班,用的这本书,并且我导也推荐我现在读,所以大概就是这时候读了。确实感觉时机刚刚好。A&amp;M是写给上个世纪七十年代的三年级本科生的讲义,很多地方不经雕琢,自成璞玉。形式化风格很是明显,鲜有大段启发性的说明或展示动机,大多是定义,定理,命题,推论的罗列,很“干”。一些证明也比较简洁,用作者自己的话说,他省去了机械的步骤;但相对的,我觉得他重要思路都点到了,真正跳步的地方比较少。我很喜欢这本书,首一的优点,它很薄,且基本的交换代数都覆盖到了,第二,它习题非常优秀, ...