循环访问数组并删除项目,而不会打破循环

我有以下for循环,当我使用splice()删除一个项目,然后我得到'秒'是未定义的。 我可以检查它是否是未定义的,但我觉得可能有一个更优雅的方法来做到这一点。 希望是简单地删除一个项目,并继续前进。

 for (i = 0, len = Auction.auctions.length; i < len; i++) { auction = Auction.auctions[i]; Auction.auctions[i]['seconds'] --; if (auction.seconds < 0) { Auction.auctions.splice(i, 1); } } 

当您执行.splice() ,该数组正在被重新编制索引,这意味着您将在删除索引时跳过索引,并且缓存的.length已过时。

要解决这个问题,你需要在.splice()之后递减,或者直接迭代…

 var i = Auction.auctions.length while (i--) { .... } 

这样,重新索引不会影响迭代中的下一个项目,因为索引只影响从当前点到数组末尾的项目,并且迭代中的下一个项目低于当前点。

这是一个很常见的问题。 解决方案是向后循环:

 for (var i = Auction.auctions.length - 1; i >= 0; i--) { Auction.auctions[i].seconds--; if (Auction.auctions[i].seconds < 0) { Auction.auctions.splice(i, 1); } } 

如果你把它们弹出来,没有关系,因为在你倒退的时候指数会被保留下来。

每次通过循环而不是在一开始就重新计算长度,例如:

 for (i = 0; i < Auction.auctions.length; i++) { auction = Auction.auctions[i]; Auction.auctions[i]['seconds'] --; if (auction.seconds < 0) { Auction.auctions.splice(i, 1); i--; //decrement } } 

这样你就不会超出界限。

编辑:在if语句中添加一个递减。

虽然你的问题是关于从正在迭代的数组中删除元素而不是有效地删除元素(除了一些其他处理),我认为如果在类似的情况下应该重新考虑它。

这种方法的算法复杂度是O(n^2)作为拼接函数,并且for循环遍历数组(拼接函数在最坏情况下移动数组的所有元素)。 相反,您可以将所需的元素推送到新的数组中,然后将该数组分配给所需的变量(刚刚迭代)。

 var newArray = []; for (var i = 0, len = Auction.auctions.length; i < len; i++) { auction = Auction.auctions[i]; auction.seconds--; if (!auction.seconds < 0) { newArray.push(auction); } } Auction.auctions = newArray; 

你也可以使用ECMAScript 5引入的数组函数(不知道版本:()。

 Auction.auctions = Auction.auctions.filter(function(auction) { return --auction.seconds >=0; }); 
 Auction.auction = Auction.auctions.filter(function(el) { return --el["seconds"] > 0; }); 

另一个简单的解决方法来消化数组元素一次:

 while(Auction.auctions.length){ // From first to last... var auction = Auction.auctions.shift(); // From last to first... var auction = Auction.auctions.pop(); // Do stuff with auction } 

这是正确使用拼接的另一个例子。 这个例子即将从“数组”中删除“属性”。

 for (var i = array.length; i--;) { if (array[i] === 'attribute') { array.splice(i, 1); } } 
 for (i = 0, len = Auction.auctions.length; i < len; i++) { auction = Auction.auctions[i]; Auction.auctions[i]['seconds'] --; if (auction.seconds < 0) { Auction.auctions.splice(i, 1); i--; len--; } } 

尝试在循环时将数组转换为newArray:

 var auctions = Auction.auctions; var auctionIndex; var auction; var newAuctions = []; for ( auctionIndex = 0; auctionIndex < Auction.auctions.length; auctionIndex++) { auction = auctions[auctionIndex]; if (auction.seconds >= 0) { newAuctions.push( auction); } } Auction.auctions = newAuctions; 

你可以通过查看并使用shift()