js如何合并两个数组去重

在javascript中合并两个数组并去除重复项,最简洁高效的方法是使用set结合展开运算符。1. 对于原始类型值,直接使用[…new set([…arr1, …arr2])]即可完成合并与去重,set会自动处理唯一性,包括将nan视为单一值;2. 对于对象数组,因set基于引用判断相等,需采用基于唯一id的map去重法:遍历合并后的数组,以对象id为键存入map,后出现的同id对象会覆盖前者,最后转回数组;3. 也可尝试json.stringify序列化对象后用set去重,但该方法受限于属性顺序、不可序列化值(如函数、undefined)及循环引用问题,适用场景有限;4. 性能上,set和map方案平均时间复杂度为o(n),远优于循环嵌套indexof的o(n²),优化关键在于选择合适算法:原始类型用set,对象类型优先基于唯一id使用map,并避免对无重复数据做冗余去重操作。该策略兼顾效率、可读性与实用性,是处理数组合并去重的推荐方案。

js如何合并两个数组去重

在JavaScript中合并两个数组并去除重复项,通常最简洁且高效的方法是利用

Set

数据结构的特性,结合展开运算符(

...

)来完成。这不仅能快速合并,还能自动处理原始类型值的去重。

js如何合并两个数组去重

合并和去重数组,我通常会倾向于使用

Set

。它提供了一种非常直观且性能不错的方案。

function mergeAndDeduplicateArrays(arr1, arr2) {  // 使用展开运算符合并数组,然后通过Set自动去重  const combinedSet = new Set([...arr1, ...arr2]);  // 将Set转换回数组  return Array.from(combinedSet);  // 或者更简洁地:return [...new Set([...arr1, ...arr2])];}// 示例const arrayA = [1, 2, 3, 4, 'a', 'b', null, undefined];const arrayB = [3, 4, 5, 6, 'b', 'c', null, undefined, NaN]; // NaN会被视为一个,但两个NaN是不同的const result = mergeAndDeduplicateArrays(arrayA, arrayB);console.log(result); // [1, 2, 3, 4, 'a', 'b', null, undefined, 5, 6, 'c', NaN]

这个方法对于数字、字符串、布尔值、

null

undefined

等原始类型表现完美。

Set

内部会确保每个值都是唯一的,

NaN

虽然不等于自身,但在

Set

中会被视为唯一的一个值。

js如何合并两个数组去重

为什么Set是处理数组去重合并的优选方案?

在我看来,

Set

之所以成为JavaScript中处理数组去重合并的首选,主要在于其设计哲学与实际效率。它就是为了存储不重复的值而生的,这与我们的需求完美契合。

首先,

Set

内置去重能力是其最大的优势。当你向一个

Set

添加元素时,它会自动检查该元素是否已经存在。如果存在,就不会重复添加;如果不存在,则会加入。这种机制省去了我们手动编写复杂的循环和条件判断来检查重复项的麻烦,代码自然就更简洁、更易读。

js如何合并两个数组去重

其次,从性能角度看,

Set

的查找和插入操作通常具有接近O(1)的平均时间复杂度(虽然在最坏情况下可能退化,但对于大多数实际场景,其性能表现都非常出色)。这意味着无论数组有多大,处理原始类型时,

Set

都能提供相当快的去重速度。相比之下,如果采用传统的手动遍历加

indexOf

includes

去重,时间复杂度可能达到O(n^2),在大数据量面前会显得非常慢。

再者,

Set

在处理

NaN

undefined

等特殊值时,行为也符合直觉。

NaN

在JavaScript中是一个很特别的值,它不等于自身。但

Set

在处理

NaN

时,会将其视为一个唯一的元素。比如,你往

Set

里加两个

NaN

,最终

Set

里只会有一个

NaN

。这避免了一些潜在的陷阱。

总的来说,

Set

提供了一种声明式、高效且语义清晰的方式来解决数组合并去重的问题,让开发者可以把精力放在更核心的业务逻辑上,而不是纠结于去重的实现细节。

合并去重时,如何处理数组中包含对象的情况?

这是一个常见的“坑”,也是

Set

直接去重方案的局限性所在。当数组中包含对象时,

Set

的默认去重机制可能不会按照你预期的那样工作。因为

Set

使用严格相等(

===

来判断值的唯一性。对于对象来说,即使两个对象拥有完全相同的属性和值,只要它们在内存中是不同的引用,

Set

就会认为它们是两个不同的对象。

比如:

[{id: 1, name: 'A'}]

[{id: 1, name: 'A'}]

,这两个对象在

Set

看来是不同的。

要解决这个问题,我们需要引入一些自定义的逻辑,核心思路是:定义“重复”的标准。通常,我们会基于对象的一个或多个唯一属性(比如

id

uuid

key

等)来判断对象是否重复。

以下是几种处理策略:

基于唯一ID属性去重(推荐且常用)这是最常见也最实用的方法。如果你的对象都有一个唯一的标识符(如

id

),你可以利用这个

id

来判断对象是否重复。

function mergeAndDeduplicateObjectsById(arr1, arr2) {  const combined = [...arr1, ...arr2];  const uniqueMap = new Map(); // 使用Map来存储唯一的对象,key为id  for (const item of combined) {    if (item && item.id !== undefined) { // 确保对象存在且有id属性      // 如果Map中没有这个id,或者新对象的版本更“新”(根据业务逻辑决定)      // 这里我们简单地以id为key存储,后来的同id对象会覆盖前面的      uniqueMap.set(item.id, item);    }  }  return Array.from(uniqueMap.values());}const arrObj1 = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}];const arrObj2 = [{id: 2, name: 'Robert'}, {id: 3, name: 'Charlie'}];const resultObj = mergeAndDeduplicateObjectsById(arrObj1, arrObj2);// 结果可能取决于你希望保留哪个同ID对象,这里是后者覆盖前者console.log(resultObj);// 预期输出:[{id: 1, name: 'Alice'}, {id: 2, name: 'Robert'}, {id: 3, name: 'Charlie'}]

这种方法高效,因为

Map

Set

get

操作也是接近O(1)的平均时间复杂度。

将对象转换为字符串去重(适用于简单、可序列化对象)如果你确定对象的所有属性都是可JSON序列化的,并且属性顺序不影响唯一性判断,可以考虑将对象

JSON.stringify

成字符串,然后用

Set

去重字符串。

function mergeAndDeduplicateObjectsByStringify(arr1, arr2) {  const combined = [...arr1, ...arr2];  const uniqueStrings = new Set();  const uniqueObjects = [];  for (const item of combined) {    try {      const itemString = JSON.stringify(item);      if (!uniqueStrings.has(itemString)) {        uniqueStrings.add(itemString);        uniqueObjects.push(item);      }    } catch (e) {      console.warn("无法序列化对象,跳过:", item, e);      // 处理不可序列化的对象,比如包含循环引用    }  }  return uniqueObjects;}const arrObj3 = [{a:1, b:2}, {b:2, a:1}, {c:3}]; // 注意:JSON.stringify对属性顺序敏感const arrObj4 = [{a:1, b:2}, {d:4}];// 如果属性顺序不同,即使内容一样,也会被认为是不同的// [{a:1, b:2}] 和 [{b:2, a:1}] 可能会被认为是两个不同的字符串const resultStr = mergeAndDeduplicateObjectsByStringify(arrObj3, arrObj4);console.log(resultStr);

局限性:

JSON.stringify

对属性的顺序是敏感的,

{a:1, b:2}

{b:2, a:1}

会被序列化成不同的字符串。此外,它不能处理循环引用、函数、

undefined

等非JSON值。因此,这种方法只适用于结构非常简单且可控的对象。

选择哪种方法,取决于你的具体业务场景和对象结构。通常,基于唯一ID属性的去重是最健壮和推荐的方案。

合并去重操作对性能有什么影响?我们应该如何优化?

合并和去重操作的性能影响,很大程度上取决于你选择的算法、数组的大小以及数组中元素的类型。理解这些影响,能帮助我们做出更明智的优化决策。

性能影响分析:

时间复杂度:

Set

方法(针对原始类型): 通常是O(N),其中N是合并后数组的总元素数。这是因为

Set

的插入和查找操作平均是常数时间。这是最理想的情况。基于

Map

的ID去重(针对对象): 同样接近O(N)。通过对象的唯一ID作为

Map

的键,查找和插入效率很高。循环

+
indexOf

/

includes

这是效率最低的常见方法,时间复杂度为O(N^2)。每添加一个元素,都需要遍历已处理的部分来检查是否重复。当N很大时,性能会急剧下降。

JSON.stringify

Set

去重: 涉及到字符串化(O(K) K为对象属性数)和字符串的哈希计算(可能与字符串长度有关),整体性能介于O(N)和O(N^2)之间,取决于对象的复杂度和数量。

内存占用

Set

Map

都需要额外的内存来存储其内部数据结构。对于非常大的数组,这可能会是一个考虑因素,但通常在现代浏览器环境中不是瓶颈。

JSON.stringify

会创建新的字符串副本,也增加了临时内存消耗。

优化策略:

选择正确的算法:

优先使用

Set

和展开运算符来处理包含原始类型(数字、字符串、布尔值等)的数组去重。这是最直接、最高效的方案。对于包含对象的数组,务必使用基于唯一标识符(如

id

)的

Map

或自定义遍历逻辑去重。 避免直接将对象放入

Set

,因为它只会比较引用。

避免不必要的去重:

如果数据来源本身就保证了唯一性,或者你只关心合并而不关心去重,那就不要进行去重操作。在某些场景下,如果数据量非常大且频繁进行合并去重,可以考虑增量更新。只对新增或变化的部分进行去重,而不是每次都处理整个数据集。

考虑数据结构的设计:

在后端或数据源层面就保证数据的唯一性,减少前端去重的负担。例如,数据库查询结果就避免重复。如果对象去重是常见需求,确保你的对象有一个明确且易于访问的唯一ID。

性能瓶颈分析:

对于性能敏感的应用,如果发现合并去重是瓶颈,可以使用浏览器开发者工具(如Chrome DevTools的Performance面板)进行剖析,找出具体是哪一步耗时最多。有时候,瓶颈可能不在去重本身,而在前置的数据处理或后置的DOM操作。

总的来说,对于JS数组的合并去重,我的经验是:对于原始类型,

Set

就是王者,直接用就好;对于对象,关键在于你如何定义“重复”,然后用

Map

或自定义遍历来高效实现这个定义。过早的微优化往往是浪费时间,但选择正确的、高效率的算法是基础。

以上就是js如何合并两个数组去重的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1514484.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月20日 08:30:03
下一篇 2025年12月20日 08:30:17

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 为什么使用 inline-block 元素时会错位?

    inline-block 元素错位成因剖析 在使用 inline-block 元素时,可能会遇到它们错位显示的问题。如代码 demo 所示,当设置了 overflow 属性时,a 标签就会错位下沉,而未设置时却不会。 问题根源: overflow:hidden 属性影响了 inline-block …

    2025年12月24日
    000
  • 为什么我的 CSS 元素放大效果无法正常生效?

    css 设置元素放大效果的疑问解答 原提问者在尝试给元素添加 10em 字体大小和过渡效果后,未能在进入页面时看到放大效果。探究发现,原提问者将 CSS 代码直接写在页面中,导致放大效果无法触发。 解决办法如下: 将 CSS 样式写在一个单独的文件中,并使用 标签引入该样式文件。这个操作与原提问者观…

    2025年12月24日
    000
  • 为什么我的 em 和 transition 设置后元素没有放大?

    元素设置 em 和 transition 后不放大 一个 youtube 视频中展示了设置 em 和 transition 的元素在页面加载后会放大,但同样的代码在提问者电脑上没有达到预期效果。 可能原因: 问题在于 css 代码的位置。在视频中,css 被放置在单独的文件中并通过 link 标签引…

    2025年12月24日
    100
  • 为什么在父元素为inline或inline-block时,子元素设置width: 100%会出现不同的显示效果?

    width:100%在父元素为inline或inline-block下的显示问题 问题提出 当父元素为inline或inline-block时,内部元素设置width:100%会出现不同的显示效果。以代码为例: 测试内容 这是inline-block span 效果1:父元素为inline-bloc…

    2025年12月24日
    400
  • css中的浏览器私有化前缀有哪些

    css中的浏览器私有化前缀有:1、谷歌浏览器和苹果浏览器【-webkit-】;2、火狐浏览器【-moz-】;3、IE浏览器【-ms-】;4、欧朋浏览器【-o-】。 浏览器私有化前缀有如下几个: (学习视频分享:css视频教程) -webkit-:谷歌 苹果 background:-webkit-li…

    2025年12月24日
    300
  • 如何利用css改变浏览器滚动条样式

    注意:该方法只适用于 -webkit- 内核浏览器 滚动条外观由两部分组成: 1、滚动条整体滑轨 2、滚动条滑轨内滑块 在CSS中滚动条由3部分组成 立即学习“前端免费学习笔记(深入)”; name::-webkit-scrollbar //滚动条整体样式name::-webkit-scrollba…

    2025年12月24日
    000
  • css如何解决不同浏览器下文本兼容的问题

    目标: css实现不同浏览器下兼容文本两端对齐。 在 form 表单的前端布局中,我们经常需要将文本框的提示文本两端对齐,例如: 解决过程: 立即学习“前端免费学习笔记(深入)”; 1、首先想到是能不能直接靠 css 解决问题 css .test-justify { text-align: just…

    2025年12月24日 好文分享
    200
  • 关于jQuery浏览器CSS3特写兼容的介绍

    这篇文章主要介绍了jquery浏览器css3特写兼容的方法,实例分析了jquery兼容浏览器的使用技巧,需要的朋友可以参考下 本文实例讲述了jQuery浏览器CSS3特写兼容的方法。分享给大家供大家参考。具体分析如下: CSS3充分吸收多年了web发展的需求,吸收了很多新颖的特性。例如border-…

    好文分享 2025年12月24日
    000
  • 360浏览器兼容模式的页面显示不全怎么处理

    这次给大家带来360浏览器兼容模式的页面显示不全怎么处理,处理360浏览器兼容模式页面显示不全的注意事项有哪些,下面就是实战案例,一起来看一下。  由于众所周知的情况,国内的主流浏览器都是双核浏览器:基于Webkit内核用于常用网站的高速浏览。基于IE的内核用于兼容网银、旧版网站。以360的几款浏览…

    好文分享 2025年12月24日
    000
  • 如何解决css对浏览器兼容性问题总结

    css对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了ie7,6与fireofx的兼容性处理方法并 整理了一下.对于web2.0的过度,请尽量用xhtml格式写代码,而且doctype 影响 css 处理,作为w3c的标准,一定要加 doctype声名.…

    好文分享 2025年12月23日
    000
  • 关于CSS3中选择符的实例详解

    英文原文: www.456bereastreet.com/archive/200601/css_3_selectors_explained/中文翻译: www.dudo.org/article.asp?id=197注:本文写于2006年1月,当时IE7、IE8和Firefox3还未发行,文中所有说的…

    好文分享 2025年12月23日
    000
  • 阐述什么是CSS3?

    网页制作Webjx文章简介:CSS3不是新事物,更不是只是围绕border-radius属性实现的圆角。它正耐心的坐在那里,已经准备好了首次登场,呷着咖啡,等着浏览器来铺上红地毯。            CSS3不是新事物,更不是只是围绕border-radius属性实现              …

    好文分享 2025年12月23日
    000
  • 用CSS hack技术解决浏览器兼容性问题

    什么是CSS Hack?   不同的浏览器对CSS的解析结果是不同的,因此会导致相同的CSS输出的页面效果不同,这就需要CSS Hack来解决浏览器局部的兼容性问题。而这个针对不同的浏览器写不同的CSS 代码的过程,就叫CSS Hack。 CSS Hack 形式   CSS Hack大致有3种表现形…

    好文分享 2025年12月23日
    000
  • 如何使用css去除浏览器对表单赋予的默认样式

    我们在写表单的时候会发现一些浏览器对表单赋予了默认的样式,如在chorme浏览器下,文本框及下拉选择框当载入焦点时,都会出现发光的边框,并且在火狐及谷歌浏览器下,多行文本框textarea还可以自由拖拽拉大,另外还有在ie10下,当文本框输入内容后,在文本框的右侧会出现一个小叉叉,等等。不容置疑,这…

    好文分享 2025年12月23日
    000

发表回复

登录后才能评论
关注微信