开发过程中,有时候第一手拿到的数据结构可能不是我们想要的结构。
所以,本文章总结了
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]
这种扩展语法,第一、简洁,第二、不变性(不改变原数组)。当然,可以用push,push改变原数组。
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
总结
没涵盖全部,开发中很多可能,但很多情况大多数都见过,万变不离其宗。
希望能有所帮助。
最好的学习是贡献和输出。
本文正在参加「金石计划」