最近遇到一个需求,需要写一个方法,方法接受一个数组(数组中是一个个的对象)、一个属性名、一个属性的value。之后在这个方法中,将数组中有对应value和属性名的对象给删除
比如对于下面这个对象数组
const testArray =[
{name:'a',id:'999',location:[5,6]},
{name:'b',id:'998',location:[5,6]},
{name:'c',id:'997',location:[3,2]},
{name:'d',id:'998',location:[1,2]}
]
我们定义一个方法objectArrayDelete,当执行objectArrayDelete后
objectArrayDelete(testArray,'id','998')
会返回一个全新数组(id为998的对象都被删除)
const testArray =[
{name:'a',id:'999',location:[5,6]},
{name:'c',id:'997',location:[3,2]}
]
说干就干,我噼里啪啦打了一通
export const objectArrayDelete = (originArray: any[], attribute: string, value: any) => {
let newArray = originArray
for (let i = 0; i < newArray.length; i++) {
if (newArray[i][attribute] && newArray[i][attribute] === value) {
newArray.splice(i, 1)
}
}
return newArray
}
打完之后就觉得不对,这一段初看没什么问题,循环遍历newArray,当属性存在且属性的值等于我们传进来的参数value后,执行splice
因为用到了splice,这样的话会有两个问题
(1)第二行的let newArray = originArray,只会创建一个数组的引用,那么在后面执行splice的时候,看似给newArray执行的,实际上是直接给我们的原本数组执行的,这样就会非常危险而且不符合数据规范,我们希望返回的是一个新数组
(2)函数的循环逻辑不太对,当我们执行splice后,数组的长度、下标等等都已经改变,如果还按照原来的循环,先不说循环次数i会不会超出数组大小的问题,当我们的数组有多个应该被删除对象时,肯定会出现无法删除完全的事情
第一个解决思路是我们定义一个数组,这个数组保存我们需要删除的对象下标,之后我们再跑一次循环
那么这样又有一个问题就是splice必定会改变数组的下标排序,那么我们保存的下标实际上是没有意义的,这样还是会有问题
查了一下,发现可以用反向排序
export const objectArrayDelete = (originArray: any[], attribute: string, value: any) => {
let newArray = [...originArray]
for (let i = newArray.length - 1; i >= 0; i--) {
if (newArray[i][attribute] && newArray[i][attribute] === value) {
newArray.splice(i, 1)
}
}
return newArray
}
主要核心是 for (let i = newArray.length - 1; i >= 0; i--)
这里是和以往的数组遍历不同,是从数组末尾向前遍历的,当我们执行splice后,我们不用关心i下标变化的问题,因为在splice后数组前面的下标是不会变的
最后,我们再处理一下,当value是数组的时候,无法直接用===判断的问题,一个删除对象数组中含有特定属性的对象的方法就写好了
//对象数组删除某个有属性值的某一对象
export const objectArrayDelete = (originArray: any[], attribute: string, value: any) => {
let newArray = [...originArray]
if (Array.isArray(value)) {
for (let i = newArray.length - 1; i >= 0; i--) {
if (newArray[i][attribute] && newArray[i][attribute].toString() === value.toString()) {
newArray.splice(i, 1)
}
}
} else {
for (let i = newArray.length - 1; i >= 0; i--) {
if (newArray[i][attribute] && newArray[i][attribute] === value) {
newArray.splice(i, 1)
}
}
}
return newArray
}