如果您已经了解 javascript 数组的基础知识,那么是时候通过更高级的主题将您的技能提升到一个新的水平。在本系列教程中,您将探索在 JavaScript 中使用数组进行编程的中级主题。
在本文中,您将学习如何在 javaScript 中将多个数组组合成一个数组。这称为合并数组。这是一个有多种解决方案的简单问题。我将向您展示最广泛使用和最佳的合并数组的方法。
合并数组的方式取决于您是否要删除重复值以及是要修改原始数组还是创建新数组。我们将在这篇文章中看看每一种。
方法 | 修改数组? | 重复? | 时间复杂度 |
---|---|---|---|
[...]传播算子 | 不变的 | 保留重复项 | 在) |
Array.concat() | 不变的 | 保留重复项 | 在) |
Array.push() | 修改数组 | 保持重复 | 在) |
for循环 | 修改数组 | 删除重复项 | O(N 2 ) |
filter和concat | 不变的 | 删除重复项 | O(N 2 ) |
Set | 不变的 | 删除重复项 | 在) |
合并允许重复值的数组
传播算子
执行数组合并的最新和最简洁的方法之一是使用展开运算符。扩展运算符[...]语法允许连接两个或多个数组。这将创建一个新数组,而不修改父数组。
const mergedArray = [... array1 , array2 ]
此方法不会删除重复项。相反,合并数组中的所有数组元素将按照与源相同的顺序插入。下面是一个例子来帮助你理解:
const array1 = [1,2,3] const array2 = [1,2,4] const merged = [...array1, array2] console.log(merged) // [1, 2, 3, 1, 2, 4]
传播算子的时间复杂度
Spread 运算符使用[Symbol.iterator],它是对象的一个属性。在合并两个数组的情况下,展开运算符使用函数遍历数组中的每个元素.next() 。这导致 O(N) 的时间复杂度。
展开运算符的总体时间复杂度为 O(N)。
数组连接
如果您正在寻找合并数组的功能方法,Array.concat()将会很有用。此外,如果您不确定输入的类型,请使用Array.concat().
const mergedArray = array1.concat(array2)
您还可以使用以下语法:
const mergedArray = [].concat(array1, array2)
该concat函数是一种不可变的合并数组的方式。它不修改父数组,而是创建一个新的合并数组。数组项将按照与源相同的顺序插入。
const array1 = [1,2,3] const array2 = [1,2,4] const merged = [].concat(array1, array2) or const merged = array1.concat(array2) console.log(merged) // [1, 2, 3, 1, 2, 4]
该concat函数允许您合并两个或多个数组。
const mergedArray = array1.concat(array2, array3, array4 .... arrayN);
时间复杂度
该concat函数可以比扩展运算符具有更好的性能。这是因为concat使用特定于数组的优化方法。另一方面,传播算子依赖于通用的迭代协议。我在不同的浏览器上测试了一些大型数组来比较传播运算符和concat:
该concat函数的整体时间复杂度为 O(N)。
数组推送
如果数组合并方法不应该创建一个新数组,array.push将会很有用。此方法允许您将元素合并到现有数组中。新添加的元素将被插入到数组的末尾。这形成了array.push一种可变的合并方式。
array1.push(4) array2.push(2) console.log(array1) // [1, 2, 3, 4, 2]
您可以使用扩展运算符将数组推入现有数组。
const array1 = [1,2,3] const array2 = [1,2,4] array1.push(...array2) console.log(array1) // [1, 2, 3, 1, 2, 4]
当您想使用 合并两个或多个数组时array.push(),可以使用以下语法:
const array1 = [1,2,3]; const array2 = [4,5,6]; const array3 = [7,8,9]; array1.push(...[...array2, ...array3]); // [1,2,3,4,5,6,7,8,9]
时间复杂度
单个元素的数组推送操作成本为 O(1)。如果要合并 N 个元素,则需要花费 O(N)。在数组合并过程中,分配数组槽并插入新项时,将产生 O(N) 的复制成本。
的整体时间复杂度为Array.pushO(N)。
合并数组和删除重复值
传统的 For 循环
合并两个数组的传统方法涉及两个或多个基于数组数量的 for 循环。
算法
遍历新数组的每一项。
用于indexOf()判断该项目是否已经存在于旧数组中。
如果不存在,将其添加到旧数组。
function merge(array1, array2) { for (let i=0; i<array2.length; i++) if (array1.indexOf(array2[i])==-1) array1.push(array2[i]); return array1; }
时间复杂度
要使用此算法合并两个相同大小的数组,indexOf需要为新数组的 N 个元素中的每一个元素调用该方法。并且每次调用都indexOf需要 O(N) 时间来搜索旧数组。所以整体时间复杂度为 O(N 2 )。
删除重复项的 for 循环合并的总体时间复杂度为 O(N 2 )。
使用 ES5 过滤和连接
该解决方案用内置数组函数concat和替换了 for 循环filter。
concat() 可用于将多个数组合并在一起,但它不会删除重复项。
filter() 用于从合并的数组中删除重复项。就像传统的for循环一样,filter使用方法indexOf()来判断合并数组中某一项的出现。
算法
concat () 将数组组合在一起,并将它们存储在另一个数组中。
使用filter()遍历合并的数组并删除多次出现的任何项目。
function merge(array1, array2) { let arrayMerge = array1.concat(array2) return arrayMerge.filter( (item, index) => arrayMerge.indexOf(item) == index ) }
时间复杂度
为了使用此算法合并两个相同大小的数组,concat 需要 O(N) 时间。然后过滤器indexOf再次调用结果数组的每个元素,时间为 O(N 2 )。
filter和解决方案的总体时间复杂度concat为 O(N 2 )。
将数组与集合合并
ES6 提供了一个单行解决方案来合并数组而不重复。它使用扩展运算符和一个集合。
Set是 JavaScript ES6 及更高版本中不支持重复的内置数据结构。这是偏离concat()的地方——检查重复项并删除它们。我们的很多工作都是由数据结构完成的。SetSet
将数组与集合合并的代码
收集 a 中两个数组的唯一值Set。
使用展开运算符将Setback 转换回数组。
function merge(array1, array2) { return [... new Set[...array1, ...array2])]; }
时间复杂度
使用 合并两个数组Set,时间复杂度为 O(N)。
结论
在本教程中,我们看到了在 JavaScript 中合并两个数组的几种不同方法。如果您准备好合并重复项,最佳解决方案包括concat和展开运算符。
我们还看到了如何从合并的数组中删除重复项。ES6 提供的解决方案是最简单且成本最低的。时间复杂度为 O(N),这是合并两个或多个数组同时删除重复项的理想选择。
方法 | 修改数组? | 重复? | 时间复杂度 |
---|---|---|---|
[...]传播算子 | 不变的 | 保留重复项 | 在) |
Array.concat() | 不变的 | 保留重复项 | 在) |
Array.push() | 修改数组 | 保持重复 | 在) |
for循环 | 修改数组 | 删除重复项 | O(N 2 ) |
filter和concat | 不变的 | 删除重复项 | O(N 2 ) |
Set | 不变的 | 删除重复项 | 在) |
END!!!
- 传播算子
- 传播算子的时间复杂度
- 数组连接
- 时间复杂度
- 数组推送
- 时间复杂度
- 传统的 For 循环
- 算法
- 时间复杂度
- 使用 ES5 过滤和连接
- 算法
- 时间复杂度
- 将数组与集合合并
- 将数组与集合合并的代码
- 时间复杂度
发表评论