您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

提升 JavaScript 水平的 9 个基本数组难题 [JS 基础]

时间:2023-01-08 11:39:15  来源:今日头条  作者:启辰8

 

成为出色的问题解决者(这就是开发人员)没有捷径可走。

精通是以练习为代价的。 由于算法和数据结构构成了每个软件的支柱,因此练习它们应该是您的首要任务。 作为最常用的存储值序列的数据结构,数组是必不可少的。

今天,我们将通过学习如何来磨练我们的技能:

*展平一个数组
* 删除数组中的重复项
*从对象数组中删除重复项
*对对象数组进行排序
*合并两个数组
*返回两个数组之间的差异
*检查数组是否包含重复元素
*返回两个数组的交集
*查找数组中最长的字符串

俗话说“熟能生巧”。 让我们搞定它

如何展平数组:

最简单的方法是使用内置的 .flat() 方法。flat() 方法采用可选的最大深度参数。

例如,给定以下数组:

const arr = [1, 2, [3, 4], [[5, 6], [7, 8]]];

展平的代码是:

const flattened = arr.flat(2); //最大深度
console.log(flattened); // [1, 2, 3, 4, 5, 6, 7, 8]

flat() 方法返回一个新数组,所有子数组以递归方式连接到指定深度。

您还可以创建自己的递归函数,迭代数组的元素并将它们添加到新数组中,一次一个。

  • 如果一个元素是一个数组,该函数应该以该元素作为参数调用自身,然后将结果数组连接到新数组。
  • 如果一个元素不是数组,函数应该简单地将它添加到新数组中。

这是一个示例,说明如何编写递归函数来展平数组:

function flatten(arr) {
  let result = [];
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      result = result.concat(flatten(arr[i]));
    } else {
      result.push(arr[i]);
    }
  }
  return result;
}

const arr = [1, [2, [3, [4]]], 5];
console.log(flatten(arr)); // [1, 2, 3, 4, 5]

您可以使用 .reduce() 方法和三元运算符使此函数更加简洁。

function flatten(arr) {
  return arr.reduce((accumulator, currentItem) => 
    Array.isArray(currentItem)
      ? accumulator.concat(flatten(currentItem))
      : accumulator.concat(currentItem), 
  []);
}

此函数具有线性时间复杂度(这意味着它对大型数组很有效)。它还具有恒定的空间复杂度(这意味着它不会随着数组大小的增加而占用更多内存)。

如何从数组中删除重复项:

到目前为止,删除数组重复项的最简单和更简洁的方法是使用 Set 对象。

Set 对象仅存储唯一值,因此您可以从数组创建一个新集合,然后使用 Array.from() 方法将该集合转换回数组。

这是您可以使用 Set 对象执行此操作的一种方法:

const arr = [1, 2, 3, 1, 2, 3, 4, 5];

const unique = Array.from(new Set(arr));

console.log(unique); // [1, 2, 3, 4, 5]

您还可以使用我最喜爱的 .reduce()

const arr = [1, 2, 3, 1, 2, 3, 4, 5]

arr.reduce((accumulator, currentItem) => {
    if (!accumulator.includes(currentItem))
        accumulator.push(currentItem)
    return accumulator
},[])

如何对对象数组进行排序

要对对象数组进行排序,您必须从对象中选择一个属性来对数组进行排序。

然后,您可以调用 .sort() 并将其传递给比较器函数。

这是比较器函数的工作原理:

  • 需要两个参数
  • 如果第一个应该在第二个之前出现,则返回负值
  • 如果第一个应该在第二个之后,它返回一个正值
  • 如果值相等,则返回 0。

以下是如何根据 name 属性的值对对象数组进行排序:

const arr = [  
  {name: 'Bob', age: 30},  
  {name: 'Alice', age: 25},  
  {name: 'Charlie', age: 35}
];

arr.sort((a, b) => {
  if (a.name < b.name) { //你可以根据任意属性排序
    return -1;
  } else if (a.name > b.name) {
    return 1;
  } else {
    return 0;
  }
});

/*
[
  {name: 'Alice', age: 25}, 
  {name: 'Bob', age: 30}, 
  {name: 'Charlie', age: 35}
] */

您还可以使用三元运算符来制作单行版本:

arr.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);

注意:有时嵌套的三元组可能难以阅读。

请记住,sort() 方法会修改原始数组,因此如果您想保留原始数组,您应该先复制它。

如何合并2个数组

要合并两个数组,您可以使用 concat() 方法。concat() 方法返回一个包含两个数组元素的新数组。

以下是如何使用 concat() 合并两个数组的示例:

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

const merged = arr1.concat(arr2);
console.log(merged); // [1, 2, 3, 4, 5, 6]

更高级的或者更确切地说是 ES6 版本使用扩展运算符 (...)。扩展运算符将数组的元素扩展为单独的参数。

这就是它的样子

const merged = [...arr1, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]

有两种方法:

  • 创建一个包含两个数组元素的新数组
  • 不要修改原始数组。

如果你不介意修改源数组,您可以简单地使用 .push() 将另一个数组的元素添加到第一个数组的末尾。

arr1.push(...arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]

返回 2 个数组之间的差异

有以下几种区别:

  • 非对称的
  • 对称的

非对称

  • 在第一个数组中但不在第二个数组中的元素

对称

  • 在第一个数组中但不在第二个数组中的元素,以及在第二个数组中但不在第一个数组中的元素

以下是如何使用 filter() 方法查找两个数组之间的非对称差异:

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];

const difference = arr1.filter(x => !arr2.includes(x));
console.log(difference); // [1, 2]

以下是为了获得对称差异:

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];

const difference = arr1
    .filter(x => !arr2.includes(x))
    .concat(arr2.filter(x => !arr1.includes(x)));

console.log(difference); // [1, 2, 6, 7]

这种方法返回一个新数组并且不修改原始数组。

或者,您可以使用 Set 对象及其 .has() 而不是 .includes()

非对称差异:

const set = new Set(arr2);
const difference = arr1.filter(x => !set.has(x));
console.log(difference); // [1, 2]

对称差异:

const set = new Set(arr2);
const set1 = new Set(arr1)
const difference = arr1
    .filter(x => !set.has(x))
    .concat(arr2.filter(x => !set1.has(x)));

console.log(difference); // [1, 2, 6, 7]

如何检查数组是否包含重复元素

最简单的方法是使用 Set 对象和 size 属性。

Set 对象仅存储唯一值,因此您可以从数组创建一个集合并将该集合的大小与原始数组的大小进行比较。

如果集合的大小小于数组的大小,则意味着数组包含重复元素。

以下是您的操作方式:

const arr = [1, 2, 3, 4, 5, 5];

const hasDuplicates = new Set(arr).size !== arr.length;
console.log(hasDuplicates); // true

您可以使用对象(也称为散列或字典)实现相同的目的

当您遍历数组时,您将当前值设置为键,将 true 设置为键的值。

如果您尝试访问一个键并且那里已经有一个值,则意味着您找到了一个重复项。

这是其中一种方法:

const hasDuplicates = (arr) => {
    let hash = {}
   for(let i = 0; i < arr.length; i++){
       if(!hash[arr[i]]){
           hash[arr[i]] = true
       } else {
           return true;
       }
   }
    return false
}

console.log(hasDuplicates(arr)); // true

这两种方法都创建一个新对象(集合或哈希对象)并且不修改原始数组。它们还具有线性时间复杂度(它们对大型数组很有效)。

如何返回两个数组之间的交集

最常见的方法是使用 filter() 和 includes()。

代码如下:

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];

const intersection = arr1.filter(x => arr2.includes(x));
console.log(intersection); // [3, 4, 5]

这种方法返回一个新数组并且不修改原始数组。

作为替代方案,您可以(再次)使用 Set 对象和 .has() 方法

const set = new Set(arr2);
const intersection = arr1.filter(x => set.has(x));
console.log(intersection); // [3, 4, 5]

你看到模式了吗? 每当使用普通对象解决问题时,您都可以使用 Set创建一个版本,反之亦然。

如何找到数组中最长的字符串

为此,您可以使用我们流行的 .reduce() 方法和一个函数来比较这些值。

比较器函数将当前字符串的长度与前一个最长字符串的长度进行比较,如果更长则返回当前字符串,否则返回前一个最长字符串。

你可以这样做:

const arr = ['short', 'medium', 'long', 'longest'];

const longest = arr.reduce((acc, x) => x.length > acc.length ? x : acc, '');
console.log(longest); // 'longest'

这种方法创建一个新变量(acc 或累加器)并且不修改原始数组。

时间复杂度是线性的(意味着它对大型数组是有效的)。

同样可以通过使用 sort() 方法和扩展运算符 (...) 来更简洁地找到数组中最长的字符串:

const longest = [...arr].sort((a, b) => b.length - a.length)[0];
console.log(longest); // 'longest'

总结

在本文中我们介绍了:

*展平一个数组
* 删除数组中的重复项
*从对象数组中删除重复项
*对对象数组进行排序
*合并两个数组
*返回两个数组之间的差异
*检查数组是否包含重复元素
*返回两个数组的交集
*查找数组中最长的字符串

谢谢阅读!



Tags: JavaScript   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
成为出色的问题解决者(这就是开发人员)没有捷径可走。精通是以练习为代价的。 由于算法和数据结构构成了每个软件的支柱,因此练习它们应该是您的首要任务。 作为最常用的存储...【详细内容】
2023-01-08  Tags: JavaScript  点击:(1)  评论:(0)  加入收藏
什么是代码测试覆盖率?在执行一组测试期间执行的代码百分比称为测试覆盖率。 它可以衡量有多少代码库经过了测试,并可能指出代码中可能没有接受足够测试的部分。 在这篇文章...【详细内容】
2023-01-08  Tags: JavaScript  点击:(1)  评论:(0)  加入收藏
Async/await 是随 ES2017 版本在 JavaScript 中引入的一种语言功能,可在 JavaScript 中启用异步、非阻塞行为。 它建立在promise之上,提供了一种更简单、更清晰的方式来处理...【详细内容】
2023-01-07  Tags: JavaScript  点击:(0)  评论:(0)  加入收藏
JavaScript 是一种轻量级的解释型编程语言。它最初是为在网络浏览器中使用而开发的,但后来发现了其他用途,包括服务器端脚本、游戏开发、数据可视化和机器学习。JavaScript 是...【详细内容】
2023-01-03  Tags: JavaScript  点击:(14)  评论:(0)  加入收藏
了解这33个JavaScript概念绝对会让你将来的职业生涯受益无穷。话不多说,直接进入主题!1. 调用栈 调用栈是解释器(如web浏览器中的JavaScript解释器)跟踪其在调用多个函数的脚本...【详细内容】
2022-12-24  Tags: JavaScript  点击:(19)  评论:(0)  加入收藏
摘要:在前不久刚发布的 GitHub 年度报告中,Java 依旧是最受程序员欢迎的编程语言,而想要成为一名优秀的 Java 程序员,这 7 个 GitHub 代码库可能会提供助力。链接:https://java.p...【详细内容】
2022-11-29  Tags: JavaScript  点击:(21)  评论:(0)  加入收藏
你将要创造什么在本教程中,我将向您展示如何使用 JavaScript 和画布以饼图和圆环图的形式显示数字信息。什么是饼图?图表是一种统计工具,用于以图形方式表示数值数据。饼图将...【详细内容】
2022-08-31  Tags: JavaScript  点击:(111)  评论:(0)  加入收藏
在本教程中,我们将看到一个使用无限滚动方法分解页面内容的简单实现。我们将使用 HTML、CSS 和 vanilla JavaScript 来构建无限滚动功能的高性能且可访问的版本。什么是无限...【详细内容】
2022-08-31  Tags: JavaScript  点击:(246)  评论:(0)  加入收藏
Htmx 是一个库,它允许你直接从 HTML 访问现代浏览器功能,而不是使用 javascript。 要理解 htmx,首先让我们看一下 HTML 中的 a 标签:<pre class="prettyprint hljs xml" style=...【详细内容】
2022-07-18  Tags: JavaScript  点击:(125)  评论:(0)  加入收藏
构建网站时经常会用到将文本复制到剪贴板的需求,下面是常用做法,兼容旧版浏览器。 创建<input>元素,将其值设置为要复制到剪贴板上的字符串。 将<input>元素附加到当前 HTML...【详细内容】
2022-05-12  Tags: JavaScript  点击:(361)  评论:(0)  加入收藏
▌简易百科推荐
成为出色的问题解决者(这就是开发人员)没有捷径可走。精通是以练习为代价的。 由于算法和数据结构构成了每个软件的支柱,因此练习它们应该是您的首要任务。 作为最常用的存储...【详细内容】
2023-01-08  启辰8  今日头条  Tags: JavaScript   点击:(1)  评论:(0)  加入收藏
什么是代码测试覆盖率?在执行一组测试期间执行的代码百分比称为测试覆盖率。 它可以衡量有多少代码库经过了测试,并可能指出代码中可能没有接受足够测试的部分。 在这篇文章...【详细内容】
2023-01-08  启辰8  今日头条  Tags:JavaScript   点击:(1)  评论:(0)  加入收藏
Async/await 是随 ES2017 版本在 JavaScript 中引入的一种语言功能,可在 JavaScript 中启用异步、非阻塞行为。 它建立在promise之上,提供了一种更简单、更清晰的方式来处理...【详细内容】
2023-01-07  启辰8  今日头条  Tags:JavaScript   点击:(0)  评论:(0)  加入收藏
译者 | 涂承烨由于代码可见性低,使用Java脚本进行编码可能会很耗时。这里有12个优雅的JavaScript技巧,可以帮助你在2023年优化代码生成。JavaScript已经成为下一批开发人员中...【详细内容】
2023-01-06    51CTO  Tags:JavaScript   点击:(10)  评论:(0)  加入收藏
WebRTC vs WebSocket1.什么是WebRTC?WebRTC 是一组 JavaScript API,可以在两个浏览器之间建立点对点连接, 实现音频和视频等数据的传输,也可以用它创建有语音/视频通话功能的应...【详细内容】
2023-01-04  前端进阶  今日头条  Tags:WebRTC   点击:(24)  评论:(0)  加入收藏
JavaScript 是一种轻量级的解释型编程语言。它最初是为在网络浏览器中使用而开发的,但后来发现了其他用途,包括服务器端脚本、游戏开发、数据可视化和机器学习。JavaScript 是...【详细内容】
2023-01-03  游戏开发乔     Tags:JavaScript   点击:(14)  评论:(0)  加入收藏
有时候,我们需要知道当前网络的状态来做一些事情,以提升用户体验,这节课,我们来看一下,如何使用 JavaScript 来检测用户是否在线。检测连接状态我们可以利用navigator.onLine API...【详细内容】
2023-01-03  前端小智  今日头条  Tags:JavaScript   点击:(10)  评论:(0)  加入收藏
在PC时代,曾有个名为“变速齿轮”的神奇软件,可以加快或减慢系统时间。当时常用来修改游戏速度,可实现外挂一般的效果,很不可思议。本文,将用JavaScript复刻这一功能,实现一个用于...【详细内容】
2022-12-27   WangLiwen   网易号  Tags:JavaScript   点击:(14)  评论:(0)  加入收藏
了解这33个JavaScript概念绝对会让你将来的职业生涯受益无穷。话不多说,直接进入主题!1. 调用栈 调用栈是解释器(如web浏览器中的JavaScript解释器)跟踪其在调用多个函数的脚本...【详细内容】
2022-12-24  程序猿最幽默  今日头条  Tags:JavaScript   点击:(19)  评论:(0)  加入收藏
使用NodeJS开发的应用,如果需要处理大量数据,可能导致堆溢出。错误提示中,会有“JavaScript heap out of memory”,如下图:通过调试分析,会发现:在出错之前,其使用的内存量是一直增...【详细内容】
2022-12-11    网易号  Tags:NodeJS   点击:(33)  评论:(0)  加入收藏
站内最新
站内热门
站内头条