JavaScript 开发中 处理数组方法 总结【常见】【实用】【收藏】

362 阅读5分钟

开发过程中,有时候第一手拿到的数据结构可能不是我们想要的结构。

所以,本文章总结了js 求 两个数组 交集、并集、差集、补集, 以及一些数组常见的处理。

希望对看到这篇文章的人能有所帮助。

我们开始吧!

1、js 求 两个数组 交集、并集、差集、补集

const a = [1,2,3], b = [1,12,4]

/* 交集 */

const c = a.filter(v => b.indexOf(v) > -1)

const c = a.filter(v => b.includes(v))

const c = a.filter(v => new Set(b).has(v))
/* 并集 */

const c = a.concat(b.filter(v => !(a.indexOf(v) > -1) ))

const c = Array.from(new Set([...a, ...b]))
/* 差集 */

const c = a.filter(v => b.indexOf(v) === -1)

const c = a.filter(v => !(new Set(b).has(v)))
/* 补集 */

const c = a.filter(v => !(b.indexOf(v) > -1))
    .concat(b.filter(v => !(a.indexOf(v) > -1)))

const c = [ 
        ...a.filter(v => !(new Set(b).has(v))), 
        ...b.filter(v => !(new Set(a).has(v)))
    ]

2、在首尾添加一个元素

利用扩展语法在首部或者尾部添加元素

const a = [1, 2, 3]

// 在尾部添加元素
const appendedA = [...a, 4] // [1, 2, 3, 4]

// 在首部添加元素
const prependedA = [0, ...a] // [0, 1, 2, 3]

这种扩展语法,第一、简洁,第二、不变性(不改变原数组)。当然,可以用pushpush改变原数组。

3、移除数组中元素

首尾

使用slice方法

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

// 移除最后一个元素
const lastRemoved = a.slice(0, 4) // [1, 2, 3, 4] (a不受影响)

// 移除第一个元素
const firstRemoved = a.slice(1) // [2, 3, 4, 5] (a不受影响)

// 同时
const firstAndLastRemoved = a.slice(0, 4).slice(1) // [2, 3, 4]

为什么不用splice? splice会改变原数组。建议用slice,除非性能很重要。

连贯的任意位置

同样用slice方法来做

先来复习一下slice的用法:

概念: slice()方法返回一个新的数组对象,原数组不会被改变。

语法:

  • slice()
  • slice(start)
  • slice(start, end)

也就是说slice接受一个参数或者两个参数,也就是开始和结束的位置

🌰 例子:const a = [1, 2, 3, 4, 5]

只有一个参数时:slice()方法返回从参数指定位置到末尾的所有项

const b = a.slice(2) // [3, 4, 5]

两个参数时:返回开始到结束位置之间的项,但,不包括结束位置项目

const b = a.slice(2, 3) // [3]

const b = a.slice(2, 4) // [3, 4]

当只有一个参数且是负数:

(1)用数组长度加上该数来确定相应的位置。

(2)或者用数组尾部算起,比如说,-1值得是最后一个元素,-2值得是倒数第二个元素,以此类推。

const b = a.slice(-4)

(1) 数组长度 + 该数 = 5 + (-4) = 1。得出 [2, 3, 4, 5]

(2) 数组尾部算起: -4 就是倒数第4,也就是从2开始,得出 [2, 3, 4, 5]

不连贯的任意位置

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

const indexToRemove = 2

const b = [
    ...a.slice(0, indexToRemove), // [1, 2]
    ...a.slice(v + 1) // [4, 5]
] // [1, 2, 4, 5]

4、改变对象数组中的所有对象的某个值

/**
const a = [
    {
        name: '张三',
        salary: 100
    },
    {
        name: '李四',
        salary: 110
    }
]
**/

// 有一天,张三李四全部涨薪工资翻倍

const b = a.map(v => ({
    ...v,
    salary: v.salary * 2
})) 

/**
得到b:
[
    {
        name: '张三',
        salary: 200
    },
    {
        name: '李四',
        salary: 220
    }
]
**/

5、改变对象数组中的特定对象特定的属性的值

/**
const a = [
    {
        name: '张三',
        salary: 100
    },
    {
        name: '李四',
        salary: 110
    }
]
**/

// 比如说就给李四涨薪翻倍

const b = a.map((v, i) => (i === 1 ? { ...v, salary: v.salary * 2} : { ...v }))

/** 得到的b:
const b = [
    {
        name: '张三',
        salary: 100
    },
    {
        name: '李四',
        salary: 220
    }
]
**/

// 当然如果我们不确定李四的index,就需要findIndex去查他在哪

这种做法,就是做到了不违反不变性原则,当然,我们已经index,就可以index索引去改这个对象。

但是,如果这个数据,大家共用,改变了源头数据,会使得代码难以维护。

遵从,第一、(简洁性),第二、(不变性)

6、删除数组的一部分

有条件地筛选

这次我们用filter来举例。从字面意思,就是筛选,要的就留下来,不要的就走。


/** a:
const a = [
    {
        name: '张三',
        salary: 100
    },
    {
        name: '李四',
        salary: 110
    },
    {
        name: '王五',
        salary: 90
    },
    {
        name: '赵六',
        salary: 100
    }
]
**/

// 有一天,财务需要找到工资低于100的员工

const b = a.filter(v => v.salary < 100)

/** 得到的b:
const b = [
    {
        name: '王五',
        salary: 90
    }
]
**/

也可以这样写

const less = (num) => (val) => val.salary < num

const b = a.filter(less(100))

分解传入多个函数的参数的方法,也称为柯里化

去重

filter 去重

去重数组有很多种做法,这里利用indexOf和filter结合来去重,如下

const a = [1, 1, 3, 3, 8, 4, 8, 9]

const b = a.filter((v, k) => a.indexOf(v) === k) // [1, 3, 8, 4, 9]

当然还有其他做法,比如

reduce 去重

const b = a.reduce((x, y) => {
  if (!x.includes(y)) {
    return x.concat(y)
  } else {
    return x
  }
}, [])

new Set 去重

const b = Array.from(new Set(a))

等等...

7、计算数组总和

const a = [1, 2, 3, 4, 5]
const b = a.reduce((a, b) => a + b, 0)
const a = [    {        name: '张三',        salary: 100    },    {        name: '李四',        salary: 110    }]

const b = a.reduce((a, b) => a + b.salary, 0) // 210

8、扁平化数组

用原生flat,根据指定深度递归地将所有子数组元素拼接到新的数组中。

flat(depth)

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

const b = a.flat() // [1, 2, 3, 4, 5]
const a = [1, 2, [3, 4, [5, 6]]]

const b = a.flat() // [1, 2, 3, 4, [5, 6]]

// 要完全扁平化,传depth,也就是需要扁平多少层

// 比如上面的这个例子需要2层

const b = a.flat(2) // [1, 2, 3, 4, 5, 6]
const a = [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]
const b = a.flat() // 默认一层,比如说我数不清,就传Infinity无穷层

const b = a.flat(Infinity) // 全部扁平到一层 [1, 2, 3, 4, 5, 6, 7, 8, 9]

9、数组排序

const a = [1, 9, 8, 7, 2, 4, 3, 6]

const b = a.sort((x, y) => x - y)  // [1, 2, 3, 4, 6, 7, 8, 9] 这种sort方法同时也改变了a

// 如果需要做到原数组不变性, 加个slice方法

const b = a.slice().sort((x, y) => x - y) // 不改变a,也就是不改变原数组

10、生成任意大小的数组

const a = Array(10).fill().map((v, k) => k) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

11、检查数组中所有值是否满足条件

// 检查是否全部值都比10小 

const a = [1, 9, 8, 7, 2, 4, 3, 6]

const b = a.every(v => v < 10) // true

12、检查数组中至少有一个值满足条件

// 检查至少有个值等于9

const a = [1, 9, 8, 7, 2, 4, 3, 6]

const b = a.some(v => v === 9) // true

总结

没涵盖全部,开发中很多可能,但很多情况大多数都见过,万变不离其宗。

希望能有所帮助。

最好的学习是贡献和输出。

本文正在参加「金石计划」