[javascript] for 루프를 끊지 않고 배열을 반복하고 항목을 제거

다음 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가 더 이상 사용되지 않습니다.

그것을 고치려면, i후에 감소 .splice()하거나 단순히 반대로 반복 해야합니다 …

var i = Auction.auctions.length
while (i--) {
    ...
    if (...) { 
        Auction.auctions.splice(i, 1);
    } 
}

이렇게하면 재색 인화는 반복의 다음 항목에 영향을 미치지 않습니다. 색인화는 현재 점에서 배열 끝까지의 항목에만 영향을 미치고 반복의 다음 항목은 현재 점보다 낮기 때문입니다.


답변

이것은 매우 일반적인 문제입니다. 해결책은 뒤로 루프하는 것입니다.

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;

ES2015부터 우리는 Array.prototype.filter한 줄에 모두 넣을 수 있습니다 .

Auction.auctions = Auction.auctions.filter(auction => --auction.seconds >= 0);


답변

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


답변

ES6 +를 사용하는 경우 왜 Array.filter 메소드를 사용하지 않습니까?

Auction.auctions = Auction.auctions.filter((auction) => {
  auction['seconds'] --;
  return (auction.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
}