AngularJS的forEach和splice功能

23

我有一个像这样的数组:

$scope.emails = [
  {"key":"Work","value":"user@domine.com"},
  {"key":"","value":""},
   {"key":"Work","value":"user2@domine.com"}
  {"key":"","value":""}];

所以,我想要删除空的电子邮件,但是 Angular 的 forEach 方法只删除了最后一个对象,为什么?

JS 代码:

angular.forEach($scope.emails, function(email, index){
     if(email.value ===""){
       $scope.emails.splice(index, 1);

     } 

    });
我犯了哪些错误? JS Bin

请在您的问题中包含相关代码,而不仅仅是链接到JSBin。 - James Allardice
5个回答

59
问题在于您在循环过程中从数组中删除元素,因此后面的项目位于不同的索引处。您需要反向循环:
for (var i = $scope.emails.length - 1; i >= 0; i--) {
    if (!$scope.emails[i].value) {
        $scope.emails.splice(i, 1);
    }
}

这里是一个更新后的示例


splice 方法的第二个参数表示要删除的元素数量,如果您可以在事先确定它,那么您也可以在一个单独的 splice 中完成。例如,您可以使用 $scope.emails.splice(1,2) 删除数组中的最后两个电子邮件(或者 $scope.emails.splice(1),这将删除第一个元素后的所有内容)。 - link
@James Allardice,谢谢您的回复。它很好地工作了。但我的问题是,我们不能使用forEach来做这个吗? - chandu
@chandu - 不,forEach 迭代数组的方向是错误的,所以您必须使用普通循环。 - James Allardice
@link - 这只适用于数组中相关元素相邻的情况。在这种情况下很好用,但不够健壮。 - James Allardice
1
当然,这就是为什么我加上了“如果您可以在之前确定”的原因 :) OP的问题不太清楚,所以我想在备注中添加它,以防他的情况允许这样做。 - link

3

正如其他人指出的那样,代码的罪魁祸首是已被删除的数组。为了解决angular.forEach的问题,你可以尝试使用加法/赋值方法:

var filteredEmails = [];
angular.forEach($scope.emails, function(email, index){
    if(email.value !==""){
        filteredEmails.push(email);
    }
});

$scope.emails = filteredEmails;

2

indexOf在未找到项时返回-1

一种删除项的方法,且在未找到时避免删除最后一个项的方法是:

var index = $scope.items.indexOf($scope.oldItem);

if (index != -1) {
  $scope.items.splice(index, 1);
}

1
describe('Foreach Splice', function () {
  it('splicing', function () {

    var elements = [
      {name: "Kelly", age: 16},
      {name: "", age: 17},
      {name: "Becky", age: 18},
      {name: "", age: 18},
      {name: "Sarah", age: 19},
      {name: "", age: 20},
      {name: "", age: 22},
      {name: "Mareck", age: 21},
      {name: "", age: 21},
      {name: "Mareck", age: 21}
    ];

    removeEmptyEntry(elements);
    console.log(elements);
  });


  function removeEmptyEntry(elements) {
    elements.forEach(function (element, index) {
      if (!element.name) {
        elements.splice(index, 1);
        removeEmptyEntry(elements);
      }
    });
  }
});

我只想删除空值,而不是第二个索引元素。 - chandu
啊,你的意思是你想要删除空元素? - Tek

0

我没有尝试过在AngularJs中这样做,但是在Angular 4中类似的方法运行得相当不错。

angular.forEach($scope.emails, function(email){
 if(email.value ===""){
   $scope.emails.splice($scope.emails.indexOf(email), 1);
 } 

});

Angular 4 版本:

this.emailArray.forEach(email => {
  if (email.value == "") {
    this.emailArray.splice(this.emailArray.indexOf(email),1);
  }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接