循环访问数组并删除项目,而不会打破循环
我有以下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()