Mam następujące dla pętli for i kiedy używam splice()
do usunięcia elementu, wtedy dostaję, że „sekundy” są niezdefiniowane. Mogę sprawdzić, czy jest niezdefiniowany, ale wydaje mi się, że istnieje bardziej elegancki sposób na zrobienie tego. Chcemy po prostu usunąć element i kontynuować.
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);
}
}
javascript
loops
dzm
źródło
źródło
Auction.auctions[i]['seconds']--
zamiastauction.seconds--
?Odpowiedzi:
Tablica jest ponownie indeksowana po wykonaniu
.splice()
, co oznacza, że pominiesz indeks, gdy zostanie on usunięty, a Twoja pamięć podręczna.length
jest przestarzała.Aby to naprawić, musisz albo zmniejszyć
i
po.splice()
, albo po prostu iterować w odwrotnej kolejności ...W ten sposób ponowne indeksowanie nie wpływa na następny element w iteracji, ponieważ indeksowanie wpływa tylko na elementy od bieżącego punktu do końca tablicy, a następny element w iteracji jest niższy niż bieżący punkt.
źródło
To dość powszechny problem. Rozwiązaniem jest zapętlenie wstecz:
Nie ma znaczenia, czy usuniesz je z końca, ponieważ indeksy zostaną zachowane podczas cofania.
źródło
Przelicz długość za każdym razem przez pętlę zamiast na samym początku, np .:
W ten sposób nie przekroczysz granic.
EDYCJA: dodano zmniejszenie w instrukcji if.
źródło
Chociaż twoje pytanie dotyczy usuwania elementów z tablicy, która jest iterowana, a nie wydajnego usuwania elementów (oprócz niektórych innych metod przetwarzania), myślę, że należy je ponownie rozważyć, jeśli w podobnej sytuacji.
Złożoność algorytmiczna tego podejścia jest
O(n^2)
jak funkcja łączenia, a pętla for iteruje się po tablicy (funkcja łączenia przesuwa wszystkie elementy tablicy w najgorszym przypadku). Zamiast tego możesz po prostu wepchnąć wymagane elementy do nowej tablicy, a następnie po prostu przypisać tę tablicę do pożądanej zmiennej (która była właśnie iterowana).Od wersji ES2015 możemy
Array.prototype.filter
to wszystko zmieścić w jednej linii:źródło
źródło
Jeśli używasz ES6 + - dlaczego nie skorzystać z metody Array.filter?
Zauważ, że modyfikacja elementu tablicy podczas iteracji filtra działa tylko dla obiektów i nie będzie działać dla tablicy pierwotnych wartości.
źródło
Kolejne proste rozwiązanie do jednorazowego trawienia elementów tablicy:
źródło
Oto kolejny przykład prawidłowego użycia łączenia. Ten przykład ma zamiar usunąć „atrybut” z „tablicy”.
źródło
Każdej osobie, która odpowiedziała na to bardzo podstawowe pytanie kodem posiadającym splice () w pętli, która ma czas wykonania O (n 2 ), lub która poparła taką odpowiedź, w ciągu siedmiu lat od opublikowania tego pytania: powinieneś wstydzić się .
Oto proste rozwiązanie czasu liniowego dla tego prostego problemu czasu liniowego.
Kiedy uruchamiam ten fragment kodu, przy n = 1 milion, każde wywołanie filterInPlace () zajmuje od 0,013 do 0,016 sekundy. Rozwiązanie kwadratowe (np. Zaakceptowana odpowiedź) zajęłoby milion razy mniej więcej tyle.
Zauważ, że modyfikuje to oryginalną tablicę zamiast tworzyć nową tablicę; robienie tego w ten sposób może być korzystne, np. w przypadku, gdy tablica jest wąskim gardłem pojedynczej pamięci programu; w takim przypadku nie chcesz tworzyć innej tablicy o tym samym rozmiarze, nawet tymczasowo.
źródło
Array.splice(i,1)
że za każdym razem utworzę nową instancję tablicy. Jestem bardzo zawstydzony.W tym wątku jest już wiele wspaniałych odpowiedzi. Chciałem jednak podzielić się swoim doświadczeniem, gdy próbowałem rozwiązać „usunięcie n-tego elementu z tablicy” w kontekście ES5.
Macierze JavaScript mają różne metody dodawania / usuwania elementów od początku lub końca. To są:
Zasadniczo żadnej z powyższych metod nie można użyć bezpośrednio do usunięcia n-tego elementu z tablicy.
Zasadniczo pozostawia nam to tylko jedną metodę tablicową
Array.splice
do wykonania usuwania n-tego elementu (są też inne rzeczy, które możesz zrobić z tymi metodami, ale w kontekście tego pytania skupiam się na usuwaniu elementów):Oto kod skopiowany z oryginalnej odpowiedzi (z komentarzami):
Inną godną uwagi metodą jest
Array.slice
. Jednak typem zwrotnym tej metody są usunięte elementy. Nie zmienia to również oryginalnej tablicy. Zmodyfikowano fragment kodu w następujący sposób:To powiedziawszy, nadal możemy użyć
Array.slice
do usunięcia n-tego elementu, jak pokazano poniżej. Jest to jednak znacznie więcej kodu (stąd nieefektywne)źródło
Spróbuj przekształcić tablicę w newArray podczas zapętlania:
źródło
Dwa przykłady, które działają:
źródło
Spróbuj
źródło
źródło
Możesz po prostu przejrzeć i użyć
shift()
źródło