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;
});
다음은 스플 라이스를 올바르게 사용하는 또 다른 예입니다. 이 예는 '배열'에서 '속성'을 제거하려고합니다.
for (var i = array.length; i--;) {
if (array[i] === 'attribute') {
array.splice(i, 1);
}
}
배열 요소를 한 번 요약하는 또 다른 간단한 솔루션 :
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
}
ES6 +를 사용하는 경우 왜 Array.filter 메소드를 사용하지 않습니까?
Auction.auctions = Auction.auctions.filter((auction) => {
auction['seconds'] --;
return (auction.seconds > 0)
})
필터 반복 동안 배열 요소를 수정하면 객체에만 작동하며 기본 값의 배열에는 작동하지 않습니다.
실행 시간 O (n은이 루프에서 코드를 가진 스플 라이스 ()이 매우 기본적인 질문에 응답 한 모든 사람 (2) 이 질문이 게시 된 이후 일곱 년 동안, 같은 대답을 upvoted있다, 또는) : 당신이해야 부끄러워 .
다음은이 간단한 선형 시간 문제에 대한 간단한 선형 시간 솔루션입니다.
n = 1 백만 으로이 코드를 실행하면 filterInPlace ()에 대한 각 호출에 .013 ~ .016 초가 걸립니다. 2 차 해법 (예 : 수용된 답)은 백만 배나 걸릴 것입니다.
// Remove from array every item such that !condition(item).
function filterInPlace(array, condition) {
var iOut = 0;
for (var i = 0; i < array.length; i++)
if (condition(array[i]))
array[iOut++] = array[i];
array.length = iOut;
}
// Try it out. A quadratic solution would take a very long time.
var n = 1*1000*1000;
console.log("constructing array...");
var Auction = {auctions: []};
for (var i = 0; i < n; ++i) {
Auction.auctions.push({seconds:1});
Auction.auctions.push({seconds:2});
Auction.auctions.push({seconds:0});
}
console.log("array length should be "+(3*n)+": ", Auction.auctions.length)
filterInPlace(Auction.auctions, function(auction) {return --auction.seconds >= 0; })
console.log("array length should be "+(2*n)+": ", Auction.auctions.length)
filterInPlace(Auction.auctions, function(auction) {return --auction.seconds >= 0; })
console.log("array length should be "+n+": ", Auction.auctions.length)
filterInPlace(Auction.auctions, function(auction) {return --auction.seconds >= 0; })
console.log("array length should be 0: ", Auction.auctions.length)
이렇게하면 새 배열을 만들지 않고 원래 배열이 수정됩니다. 예를 들어, 어레이가 프로그램의 단일 메모리 병목 인 경우, 이와 같이 제자리에이를 수행하는 것이 유리할 수있다; 이 경우 일시적으로도 동일한 크기의 다른 배열을 만들고 싶지 않습니다.
이 스레드에는 이미 훌륭한 답변이 많이 있습니다. 그러나 ES5 컨텍스트에서 "배열에서 n 번째 요소 제거"를 해결하려고 할 때 내 경험을 공유하고 싶었습니다.
JavaScript 배열에는 시작 또는 끝에서 요소를 추가 / 제거하는 다른 방법이 있습니다. 이것들은:
arr.push(ele) - To add element(s) at the end of the array
arr.unshift(ele) - To add element(s) at the beginning of the array
arr.pop() - To remove last element from the array
arr.shift() - To remove first element from the array
본질적으로 위의 방법 중 어느 것도 배열에서 n 번째 요소를 제거하는 데 직접 사용할 수 없습니다.
주목할만한 사실은 이것이 반복하는 동안 컬렉션의 n 번째 요소를 제거 할 수있는 Java 반복자의 사용과 대조적이라는 것입니다.
이것은 기본적으로 Array.splice
n 번째 요소 제거를 수행하는 배열 방법 을 하나만 남겨 둡니다 (이 방법 으로 수행 할 수있는 다른 작업도 있지만이 질문의 맥락에서 요소 제거에 중점을 둡니다).
Array.splice(index,1) - removes the element at the index
다음은 원래 답변 (주석 포함)에서 복사 한 코드입니다.
var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length
while (i--) //decrement counter else it would run into IndexOutBounds exception
{
if (arr[i] === "four" || arr[i] === "two") {
//splice modifies the original array
arr.splice(i, 1); //never runs into IndexOutBounds exception
console.log("Element removed. arr: ");
} else {
console.log("Element not removed. arr: ");
}
console.log(arr);
}
또 다른 주목할만한 방법은 Array.slice
입니다. 그러나이 메소드의 리턴 유형은 제거 된 요소입니다. 또한 이것은 원래 배열을 수정하지 않습니다. 다음과 같이 수정 된 코드 스 니펫 :
var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length
while (i--) //decrement counter
{
if (arr[i] === "four" || arr[i] === "two") {
console.log("Element removed. arr: ");
console.log(arr.slice(i, i + 1));
console.log("Original array: ");
console.log(arr);
}
}
그럼에도 불구하고 우리는 여전히 Array.slice
아래 표시된 것처럼 n 번째 요소를 제거 하는 데 사용할 수 있습니다. 그러나 훨씬 더 많은 코드입니다 (따라서 비효율적입니다)
var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length
while (i--) //decrement counter
{
if (arr[i] === "four" || arr[i] === "two") {
console.log("Array after removal of ith element: ");
arr = arr.slice(0, i).concat(arr.slice(i + 1));
console.log(arr);
}
}
이
Array.slice
방법은 기능 프로그래밍에서 불변성을 달성하는 데 매우 중요합니다.
루핑 할 때 배열을 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;
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--;
}
}
그냥 살펴보고 사용할 수 있습니다 shift()
'development' 카테고리의 다른 글
AngularJS ng- 클릭 중지 (0) | 2020.02.19 |
---|---|
2 차원 배열을 만들기위한 구문 (0) | 2020.02.19 |
이 병합이 필요한 이유를 설명하기 위해 커밋 메시지를 입력하십시오. (0) | 2020.02.19 |
버튼 모서리를 둥글게 만드는 방법은 무엇입니까? (0) | 2020.02.19 |
Java InputStream의 내용을 OutputStream에 작성하는 쉬운 방법 (0) | 2020.02.19 |