删除数组中的重复项拼接

问题描述

我在拼接数组中的重复项时遇到问题 这是我所拥有的

users=[];

for(let i=0;i<30;i++) users.push({name: 'peter',number:'555'});

users.forEach((element,index,users) => {
  if((element.name === 'peter') && (element.number === '555')){
       users.splice(index,1);
  }
});

出于某种原因,它删除了其中一些但不是全部 当我使用 for 循环时相同:/

有什么建议吗?

解决方法

您可以通过使用标准 for 循环向后迭代数组来就地删除。

const spliceWhere = (arr,predicate) => {
  for (let i = arr.length - 1; i >= 0; i--) {
    if (predicate(arr[i])) {
       arr.splice(i,1);
    }
  }
  return arr; // Optional,for chaining
}

const users = new Array(30).fill({ name: 'peter',number: '555' });

console.log(JSON.stringify(users));

spliceWhere(
  users,({ name,number }) => name === 'peter' && number === '555'
);

console.log(JSON.stringify(users));
.as-console-wrapper { top: 0; max-height: 100% !important; }

,

大多数情况下的首选解决方案是使用内置方法 Array.prototype.filter。这与 Polywhirl 的答案不同,因为它构造了一个新数组并替换了旧数组 -

let users = [
  {name: 'peter',number:'555'},{name: 'alice',{name: 'peter',number:'111'},{name: 'bobby',{name: 'steve',number:'777'},number:'999'},];

users = users.filter(({ name,number }) => {
  return !(name == "peter" && number == "555")
});

console.log(JSON.stringify(users));

[ 
  {"name":"alice","number":"555"},{"name":"peter","number":"111"},{"name":"bobby",{"name":"steve","number":"777"},"number":"999"}
]

使用 De Morgan's Law,我们可以编写一个等效的逻辑表达式,与 filter 一起使用时感觉更自然 -

let users = [
  {name: 'peter',number }) => {
  return name != "peter" || number != "555"  // <- equivalent
});

console.log(JSON.stringify(users));
// []

[ 
  {"name":"alice","number":"999"}
]
,

根据 MDN 文档,Modifying the array during iteration

forEach() 在迭代之前不会复制数组。

例如

let a = [0,1,2,3,4,5];
a.forEach((n,I) => {
    console.log(n,I);
    a.shift();
});

每次调用 callback() 之前,都会获取 CURRENT Ia-nd 项。并且无论I是否改变,下次a都会加1,直到到达CURRENT a的末尾。

所以,你会得到:

0 0
2 1
4 2