从对象数组中移除选中对象的代码问题排查
问题:从数组中移除选中对象时出现重复元素错误
原代码如下:
//Original array let obj1 = [ {"Nome": "João", "Idade": 16, "Fone 1": "55 5555"}, {"Nome": "Pedro", "Idade": 16, "Fone 1": "55 5555"}, {"Nome": "Marcos", "Idade": 16, "Fone 1": "55 5555"}, {"Nome": "Lucas", "Idade": 16, "Fone 1": "55 5555"}, {"Nome": "Tiago", "Idade": 16, "Fone 1": "55 5555"} ]; //Array selected by the user to delete: let obj2 = [ {"Nome": "Marcos", "Idade": 16, "Fone 1": "55 5555"}, {"Nome": "Lucas", "Idade": 16, "Fone 1": "55 5555"}, ]; function deleteObj(val1, val2){ let val = []; for (const i of val1) { for (const x of val2) { JSON.stringify(i) !== JSON.stringify(x) ? val.push(i) : {}; } } return val; } console.log(deleteObj(obj1, obj2));
运行后得到错误结果,未被选中的对象被重复添加:
[ { Nome: 'João', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'João', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Pedro', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Pedro', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Marcos', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Lucas', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Tiago', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Tiago', Idade: 16, 'Fone 1': '55 5555' } ]
错误原因
你的双层循环逻辑完全错误:
对于obj1里的每一个元素,你都会和obj2里的每一个元素逐一对比——只要两者不相等,就把当前obj1的元素推入结果数组。
比如João这个对象,和obj2里的Marcos、Lucas都不相等,所以会被push两次;同理Pedro、Tiago也各被push两次;而Marcos会和Lucas不相等,Lucas会和Marcos不相等,所以也各被push一次,最终导致所有元素重复出现。
修正方案
方案1:修正原循环逻辑
判断obj1的当前元素完全不在obj2中时,再推入结果数组,用every方法实现:
function deleteObj(val1, val2){ let val = []; for (const i of val1) { // 检查当前元素是否和obj2里所有元素都不相等 const shouldKeep = val2.every(x => JSON.stringify(i) !== JSON.stringify(x)); if (shouldKeep) { val.push(i); } } return val; }
方案2:用filter简化代码
更简洁的写法,直接用数组的filter和some方法:
function deleteObj(val1, val2){ return val1.filter(item => { // 只要当前元素不在要删除的列表里,就保留 return !val2.some(deleteItem => JSON.stringify(item) === JSON.stringify(deleteItem)); }); }
方案3:更可靠的对比方式(推荐)
用JSON.stringify对比对象有局限性——如果对象键的顺序不同,即使内容一致也会被判定为不相等。如果你的对象有唯一标识(比如Nome字段是唯一的),可以用更高效、可靠的方式:
function deleteObj(val1, val2){ // 先把要删除的名字存入Set,提升查询性能 const deleteNames = new Set(val2.map(item => item.Nome)); // 过滤掉名字在删除列表里的元素 return val1.filter(item => !deleteNames.has(item.Nome)); }
运行修正后的代码,就能得到正确结果:
[ { Nome: 'João', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Pedro', Idade: 16, 'Fone 1': '55 5555' }, { Nome: 'Tiago', Idade: 16, 'Fone 1': '55 5555' } ]
内容的提问来源于stack exchange,提问作者Jorge
相关产品推荐
相关产品推荐

