Mam dwie tablice. Pierwsza tablica zawiera jakieś wartości, podczas gdy druga tablica zawiera indeksy wartości, które powinny zostać usunięte z pierwszej tablicy. Na przykład:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
Chcę usunąć wartości obecne w indeksach 0,2,4
z valuesArr
. Pomyślałem, że splice
metoda rodzima może pomóc, więc wymyśliłem:
$.each(removeValFromIndex,function(index,value){
valuesArr.splice(value,1);
});
Ale to nie zadziałało, ponieważ po każdym splice
indeksy wartości w valuesArr
były różne. Mógłbym rozwiązać ten problem, używając tymczasowej tablicy i kopiując wszystkie wartości do drugiej tablicy, ale zastanawiałem się, czy istnieją jakieś natywne metody, do których możemy przekazać wiele indeksów, w których można usunąć wartości z tablicy.
Wolałbym rozwiązanie jQuery. (Nie jestem pewien, czy mogę użyć grep
tutaj)
źródło
$.each(rvm.reverse(), function(e, i ) {})
removeValFromIndex
zostanie posortowane w kolejności rosnącejOto jeden, którego używam, gdy nie wybieram lodash / underscore:
źródło
slice
będziesz musiał ponownie obliczyć indeksy do usunięcia (-1 zIndexestoBeRemoved
), ale to faktycznie działa!IndexesToBeRemoved
tablica jest sortowana rosnąco.IndexesToBeRemoved
jest posortowane (rosnąco).Nie,
in-place
ale można to zrobić za pomocągrep
iinArray
funkcjijQuery
.sprawdź to skrzypce.
źródło
valuesArr = $.grep(...);
Sugeruję użycie Array.prototype.filter
źródło
Odniesienie do MDN jest tutaj
źródło
W czystym JS możesz zapętlić tablicę od tyłu, więc
splice()
nie zepsujesz indeksów kolejnych elementów w pętli:źródło
Z
O(n)
czasem trzeba odpowiedzieć :). Problem z rozwiązaniem splice polega na tym, że ze względu na to, że podstawowa implementacja tablicy jest dosłownie tablicą , każdesplice
wywołanie zajmie trochęO(n)
czasu. Jest to najbardziej widoczne, gdy ustawiamy przykład, aby wykorzystać to zachowanie:To usuwa elementy od środka do początku, stąd każde usunięcie wymusza na silniku js skopiowanie
n/2
elementów, mamy(n/2)^2
w sumie operacje kopiowania, które są kwadratowe.Rozwiązanie łączenia (zakładając, że
is
jest już posortowane w kolejności malejącej, aby pozbyć się narzutów) wygląda następująco:Jednak nie jest trudno zaimplementować liniowe rozwiązanie czasu, rekonstruując tablicę od zera, używając maski, aby zobaczyć, czy kopiujemy elementy, czy nie (sortowanie przesunie to
O(n)log(n)
). Oto taka implementacja (niemask
jest to logiczna inwersja dla prędkości):Uruchomiłem to na jsperf.com i nawet
n=100
metoda łączenia jest o pełne 90% wolniejsza. W przypadku większychn
różnica ta będzie znacznie większa.źródło
Quick ES6 jedna wkładka:
źródło
removeValFromIndex
aSet()
i użyjeszremoveValFromIndex.has
zamiastincludes
.Proste i wydajne (liniowa złożoność) rozwiązanie wykorzystujące filtr i zestaw :
Ogromną zaletą tej implementacji jest to, że operacja wyszukiwania Set (
has
funkcja) zajmuje stały czas, na przykład jest szybsza niż odpowiedź Nevace'a.źródło
Działa to dobrze dla mnie i działa również podczas usuwania z tablicy obiektów:
Może istnieć krótszy, bardziej efektywny sposób napisania tego, ale to działa.
źródło
Proste rozwiązanie wykorzystujące ES5. Wydaje się to bardziej odpowiednie dla większości dzisiejszych aplikacji, ponieważ wielu nie chce już polegać na jQuery itp.
Kiedy indeksy do usunięcia są posortowane w kolejności rosnącej:
Gdy indeksy do usunięcia nie są posortowane:
źródło
Możesz poprawić swój kod, zastępując
removeValFromIndex
goremoveValFromIndex.reverse()
. Jeśli nie ma gwarancji, że ta tablica będzie używać kolejności rosnącej, możesz zamiast tego użyćremoveValFromIndex.sort(function(a, b) { return b - a })
.źródło
removeValFromIndex
są w porządku rosnącym.Oto jedna możliwość:
Przykład na jsFiddle
MDN w witrynie Array.prototype.reduceRight
źródło
Jeśli używasz underscore.js , możesz użyć
_.filter()
do rozwiązania problemu.Dodatkowo, jeśli próbujesz usunąć elementy za pomocą listy elementów zamiast indeksów, możesz po prostu użyć
_.without()
:Teraz
filteredArr
powinno["V2", "V4", "V5"]
źródło
filter + indexOf (IE9 +):
Lub z filtrem ES6 + znajdź (Edge +):
źródło
Oto szybki numerek.
źródło
Wygląda na to, że aplikacja Apply może być tym, czego szukasz.
może coś takiego zadziała?
źródło
.splice()
metoda nie oczekuje listy elementów do usunięcia, oczekuje pojedynczego indeksu elementu, od którego rozpocznie się usuwanie, a następnie liczby elementów do usunięcia ...W przypadku wielu przedmiotów lub unikatowego przedmiotu:
Sugeruję użycie Array.prototype.filter
Nigdy nie używaj indexOf, jeśli już znasz ten indeks !:
Robić:
with Hashes ... using Array.prototype.map
źródło
To działa. Jednak w trakcie tego procesu utworzyłbyś nową tablicę. Nie jestem pewien, czy tego chcesz, czy nie, ale technicznie byłoby to tablica zawierająca tylko żądane wartości.
źródło
Możesz spróbować użyć
delete array[index]
To nie usunie całkowicie elementu, ale raczej ustawi wartość naundefined
.źródło
Możesz skonstruować
Set
tablicę z tablicy, a następnie utworzyć tablicę z zestawu.źródło