在项目实践中用更优雅的方式处理数组问题

发布时间:2019-08-11 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了在项目实践中用更优雅的方式处理数组问题脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

图片描述

在最近的项目中,遇到了比较多处理数组的场景,比如要对数组里面某个元素的某一个字段进行抽取归类或者判断数组当中的某个元素是否符满足判断条件等。

网上关于使用ES5新的的API来代替for循环的文章已经非常多,它们有的详细讨论了API的用法,有的详细分析各自的性能,还有的整理了使用中的注意事项。因此,本文不再对这些API的详细使用方式进行赘述,仅仅从个人角度出发,整理归纳一些在项目实践中遇到的能够更加优雅处理数组遍历的例子。

1、使用Set处理数组去重和元素剔除问题

Setes6新增的一种数据结构,它和数组非常相似,但是成员的值都是唯一的,没有重复的值。它提供了4个语义化的API:

  1. add(value):添加某个值,返回Set结构本身。

  2. delete(value):删除某个值,返回一个布尔值,表示删除是否成功。

  3. has(value):返回一个布尔值,表示该值是否为Set的成员。

  4. clear():清除所有成员,没有返回值。

参考自@阮一峰 老师的《ECMAScript 6 入门》

那么我们可以用Set来干嘛呢?

第一个用法,数组去重。对于一个一维数组,我们可以先把它转化成Set,再配合...解构运算符重新转化为数组,达到去重的目的。请看例子:

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

const newArr = [...new Set(arr)]

console.LOG(newArr)

// [1, 2, 3, 4, 5]

值得注意的是,这个方法不能对元素为“对象”的数组奏效:

const arr = [{ name: 'Alice', age: 12 }, { name: 'Alice', age: 12 }, { name: 'Bob', age: 13 }]

const newArr = [...new Set(arr)]

console.log(newArr)

// [{ name: 'Alice', age: 12 }, { name: 'Alice', age: 12 }, { name: 'Bob', age: 13 }]

这是因为Set判断元素是否重复的办法类似于===运算符,两个对象总是不相等的。

除了去重,Set提供的delete()方法也是非常实用。在以往的做法中,如果要删除数组中指定的元素,我们需要先获取该元素所在下标,然后通过splice()方法去删除对应下标的元素,在理解上容易引起混乱:

// 我想删除数组当中值为2的元素
const arr = [1, 2, 3]
const index = arr.indexOf(2)
if (index !== -1) {
    arr.splice(index, 1)
}

console.log(arr)

// [1, 3]

使用Set就清晰多了:

const arr = [1, 2, 3]
const set = new Set(arr)
set.delete(2)
arr = [...set]

console.log(arr)

// [1, 3]

2、 使用map()方法和对象解构语法提取字段

请求后台接口返回的数据中,很可能会遇到下面这种数据格式

studentInfo = [
  { name: 'Alice', age: 18, no: 2 },
  { name: 'Bob', age: 16, no: 5 },
  { name: 'Candy', age: 17, no: 3 },
  { name: 'Den', age: 18, no: 4 },
  { name: 'Eve', age: 16, no: 1 },
]

当我们要获取姓名列表、年龄列表和编号列表的时候,我们可以通过map()再配合对象的解构语法方便快捷地进行处理:

const nameList = studentInfo.map(({ name }) => name)
const ageList = studentInfo.map(({ age }) => age)
const noList = studentInfo.map(({ no }) => no)

// nameList: [ 'Alice', 'Bob', 'Candy', 'Den', 'Eve' ]
// ageList: [ 18, 16, 17, 18, 16 ]
// noList: [ 2, 5, 3, 4, 1 ]

3、使用filter()方法和对象解构语法过滤数组

接上上面的例子,如果我想获取一个“年龄小于等于17岁”的新列表,应该怎么做呢?类似map()方法,我们可以用filter()方法进行过滤:

const newStudentInfo = studentInfo.filter(({ age }) => {
  return age <= 17
})

/*
newStudentInfo: [
  { name: 'Bob', age: 16, no: 5 },
  { name: 'Candy', age: 17, no: 3 },
  { name: 'Eve', age: 16, no: 1 }
]
*/

4、借助includes()方法求两个数组的差集

假设我们有以下两个数组:

VAR a = [1, 2, {s:3}, {s:4}, {s:5}]
var b = [{s:2}, {s:3}, {s:4}, 'a']

我们应该如何找到它们的差集呢?传统的方法可能需要把它们以Object形式hash化,但其实我们可以通过.includes()方法更加优雅方便地找出差集,代码如下:

var a = [1, 2, {s:3}, {s:4}, {s:5}].map(item => JSON.stringify(item))
var b = [{s:2}, {s:3}, {s:4}, 'a'].map(item => JSON.stringify(item))

var diff = a.concat(b)
            .filter(v => !a.includes(v) || !b.includes(v))
            .map(item => JSON.parse(item))
            
// diff: [1, 2, {s:5}, {s:2}, "a"]

至于为什么要JSON.stringify(),是因为要对比两个“对象元素”是否相等,是无法直接以“对象”形式比较的(永远返回不相等)。

5、后记

本文篇幅较短,难度也相对简单,以上都是一些平时实践中发现的技巧,希望可以对读者们有所启发。如果你也有一些比较优雅好玩的技巧,不妨和我交流分享喔~

脚本宝典总结

以上是脚本宝典为你收集整理的在项目实践中用更优雅的方式处理数组问题全部内容,希望文章能够帮你解决在项目实践中用更优雅的方式处理数组问题所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。