Pytanie Jak usunąć konkretny element z tablicy w JavaScript?


Mam tablicę liczb całkowitych i używam .push() metoda dodawania do niego elementów.

Czy istnieje prosty sposób na usunięcie określonego elementu z tablicy? Odpowiednik czegoś podobnego array.remove(int);.

Muszę użyć rdzeń JavaScript - Nie ramy są dozwolone.


6131
2018-04-23 22:17


pochodzenie


Jeśli potrzebujesz wsparcia <IE9 (westchnienie) następnie sprawdź to pytanie SO Jeżeli chodzi o indexOf w IE. - Scotty.NET
(lodash) array = ["a", "b", "c"]; _.pull (tablica, "a") // array => ['b', 'c']; Zobacz też stackoverflow.com/questions/5767325/... - Chun Yang
metoda filtrowania potrafię robić, co chcesz. - Salvador Dali
Możesz użyć polecenia delete, ale nie zmieni ono indeksu, zamiast tego ustawi to miejsce na "niezdefiniowane × 1". Na przykład: var list = [1,2,3,4,5,6] -> delete list [1] -> [1, undefined × 1, 3, 4, 5, 6]. - DevWL
Oto test wydajności dwóch głównych możliwości: jsben.ch/#/b4Ume - EscapeNetscape


Odpowiedzi:


Znaleźć index elementu tablicy, który chcesz usunąć, a następnie usuń ten indeks za pomocą splice.

Metoda splice () zmienia zawartość tablicy przez usunięcie   istniejące elementy i / lub dodawanie nowych elementów.

var array = [2, 5, 9];
var index = array.indexOf(5);
if (index > -1) {
  array.splice(index, 1);
}
// array = [2, 9]

Drugi parametr splice to liczba elementów do usunięcia. Zauważ, że splice modyfikuje tablicę w miejscu i zwraca nową tablicę zawierającą elementy, które zostały usunięte.


Uwaga: obsługa przeglądarki dla indexOf jest ograniczony


8923
2018-04-23 22:23



@Peter, tak, możesz mieć rację. W tym artykule objaśniono więcej i zastosowano obejście dla niezgodnych przeglądarek: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/... - Tom Wadley
Niebezpieczny! Jeśli pracujesz z wartościami dynamicznymi (dodaj i usuń wartości dynamiczne z tablicy), a wartość nie istnieje w tablicy (indeks staje się -1), powyższy kod usunie ostatni element tablicy. - Adrian P.
@AlexandreWiechersVaz Oczywiście zachowuje porządek, gdyby tak nie było, byłoby bezwartościowe - TheZ
Możesz pokonać problem z obsługą przeglądarki IE, włączając kod tutaj podane
@AdrianP. array.indexOf(testValue) na pustej tablicy będzie -1, a jeśli testujesz to, to bez splicingu. Może od tego czasu zmieniła się odpowiedź. - UpTheCreek


Nie wiem, jak się spodziewasz array.remove(int) zachowywać się. Są trzy możliwości, o których mogę pomyśleć, że możesz chcieć.

Aby usunąć element tablicy w indeksie i:

array.splice(i, 1);

Jeśli chcesz usunąć każdy element z wartością number z tablicy:

for(var i = array.length - 1; i >= 0; i--) {
    if(array[i] === number) {
       array.splice(i, 1);
    }
}

Jeśli chcesz tylko uczynić element indeksem i już nie istnieje, ale nie chcesz zmieniać indeksów pozostałych elementów:

delete array[i];

896
2018-04-23 22:20



delete nie jest poprawnym sposobem usunięcia elementu z tablicy! - Felix Kling
@FelixKling To zależy, działa, jeśli chcesz, aby tak było array.hasOwnProperty(i) zwraca false i przywrócić element na tej pozycji undefined. Przyznaję jednak, że nie jest to zbyt powszechne. - Peter Olson
delete nie aktualizuje długości tablicy ani nie usuwa elementu, tylko zastępuje go specjalną wartością undefined. - diosney
@diosney Nie wiem, co masz na myśli mówiąc, że to naprawdę nie usuwa elementu. Co więcej, robi więcej niż tylko zastępuje wartość w tym indeksie undefined: usuwa zarówno indeks, jak i wartość z tablicy, tj. po delete array[0], "0" in array zwróci false. - Peter Olson
delete jest dobrym mechanizmem, jeśli masz do czynienia z nazwanymi właściwościami var array=[];array['red']=1;array['green']=2;array['blue']=3;delete array['green']; - Jefferey Cave


Edytowany w dniu 2016 października

  • Czy to proste, intuicyjne i wyraźne (https://en.wikipedia.org/wiki/Occam%27s_razor)
  • Zrób to niezmiennie (oryginalna tablica pozostaje niezmieniona)
  • Zrób to ze standardowymi funkcjami JS, jeśli Twoja przeglądarka ich nie obsługuje - użyj polyfill

W tym przykładzie kodu używam "array.filter (...)" funkcja do usuwania niechcianych elementów z tablicy, funkcja ta nie zmienia oryginalnej tablicy i tworzy nową. Jeśli Twoja przeglądarka nie obsługuje tej funkcji (np. IE przed wersją 9 lub Firefox przed wersją 1.5), rozważ użycie filtr polyfill z Mozilli.

Usuwanie przedmiotu (ECMA-262 Edition 5 code aka oldstyle JS)

var value = 3

var arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(function(item) { 
    return item !== value
})

console.log(arr)
// [ 1, 2, 4, 5 ]

Usuwanie pozycji (kod ES2015)

let value = 3

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => item !== value)

console.log(arr)
// [ 1, 2, 4, 5 ]

WAŻNY ES2015 "() => {}" Składnia funkcji strzałek nie jest w ogóle obsługiwana w IE, Chrome przed wersją 45, Firefox przed wersją 22, Safari przed wersją 10. Aby użyć składni ES2015 w starszych przeglądarkach, możesz użyć BabelJS


Usuwanie wielu elementów (kod ES2016)

Dodatkową zaletą tej metody jest możliwość usunięcia wielu elementów

let forDeletion = [2, 3, 5]

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!

console.log(arr)
// [ 1, 4 ]

WAŻNY Funkcja "array.includes (...)" nie jest obsługiwana w IE, Chrome przed wersją 47, Firefox przed wersją 43, Safari przed wersją 9 i Edge przed wersją 14, więc tutaj jest polyfill z Mozilli

Usuwanie wielu elementów (najnowocześniejszy eksperymentalny JavaScript ES2018?)

// array-lib.js

export function remove(...forDeletion) {
    return this.filter(item => !forDeletion.includes(item))
}

// main.js

import { remove } from './array-lib.js'

let arr = [1, 2, 3, 4, 5, 3]

// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)

console.log(arr)
// [ 1, 4 ]

Wypróbuj sam w BabelJS :)

Odniesienie


678
2017-12-19 19:54



ale czasami chcemy usunąć element z oryginalnej tablicy (niezmiennej), na przykład tablica używana w Angular 2 * ngDla dyrektywy - Ravinder Payal
Lepsze niż przyjęte rozwiązanie, ponieważ nie zakłada się tylko jednego wystąpienia dopasowania, a niezmienność jest preferowana - Greg
Korzystanie z filtru jest o wiele przyjemniejsze niż używanie splice. Zbyt proste. - user3344977
filter musi być znacznie wolniejszy w przypadku dużej tablicy? - Nathan
Super powolna metoda. - highmaintenance


Zależy od tego, czy chcesz zachować puste miejsce, czy nie.

Jeśli chcesz mieć pusty slot, usuń wszystko:

delete array[ index ];

Jeśli nie, powinieneś użyć splatać metoda:

array.splice( index, 1 );

A jeśli potrzebujesz wartości tego przedmiotu, możesz po prostu przechowywać zwracany element tablicy:

var value = array.splice( index, 1 )[0];

Jeśli chcesz zrobić to w dowolnej kolejności, możesz użyć array.pop() dla ostatniego lub array.shift() dla pierwszego (i oba zwracają wartość elementu).

A jeśli nie znasz indeksu przedmiotu, możesz go użyć array.indexOf( item ) zdobyć to (w if() dostać jeden przedmiot lub w while() aby uzyskać wszystkie z nich). array.indexOf( item ) zwraca indeks lub -1, jeśli nie został znaleziony.


359
2018-04-23 22:32



Warto to zauważyć var value nie będzie przechowywać usuniętej wartości, ale tablicę zawierającą usuniętą wartość. - Jakub
delete nie jest prawidłowym sposobem usuwania elementu z tablicy !! - Progo
Jeśli chcesz "opróżnić boks", użyj array[index] = undefined;. Za pomocą delete zniszczy optymalizację. - Bergi
@Jakub bardzo dobry komentarz, ponieważ zrozumiałem, że straciłem dużo czasu i myślałem, że mój kod aplikacji jest w jakiś sposób zepsuty ... - Pascal


Znajomy miał problemy w Internet Explorer 8i pokazał mi, co zrobił. Powiedziałem mu, że to źle, i powiedział mi, że dostał odpowiedź tutaj. Aktualna najlepsza odpowiedź nie będzie działać we wszystkich przeglądarkach (na przykład Internet Explorer 8) i usunie tylko pierwsze wystąpienie tego elementu.

Usuń WSZYSTKIE instancje z tablicy

function remove(arr, item) {
    for (var i = arr.length; i--;) {
        if (arr[i] === item) {
            arr.splice(i, 1);
        }
    }
}

Pętla przechodzi przez tablicę do tyłu (ponieważ indeksy i długość zmieniają się w miarę usuwania elementów) i usuwa element, jeśli zostanie znaleziony. Działa we wszystkich przeglądarkach.


228
2017-08-10 19:21



@sroes to nie powinno być, ponieważ zaczyna się pętla i = arr.length -1 lub i-- czyniąc to samo, co indeks maks. arr.length jest po prostu wartością początkową dla i. i-- zawsze będzie prawda (i zmniejszanie o 1 w każdej pętli op), aż będzie równa 0 (wartość falsy) i pętla zostanie zatrzymana. - gabeno
Druga funkcja jest raczej nieefektywna. Przy każdej iteracji "indexOf" rozpocznie wyszukiwanie od początku tablicy. - Ujeenator
@AmberdeBlack, w kolekcji z więcej niż 1 wystąpieniem pozycja, o wiele lepiej jest zadzwonić do filtrzamiast tego metoda arr.filter(function (el) { return el !== item }), unikając konieczności wielokrotnego mutowania tablicy. Zużywa to nieco więcej pamięci, ale działa o wiele wydajniej, ponieważ trzeba wykonać mniej pracy. - Eugene Kuzmenko
@AJJey, jest dostępny tylko z IE9 +. Nadal istnieje szansa, że ​​to nie zadziała. - Ujeenator
Ta odpowiedź zadziałała, ponieważ potrzebowałem kilku przedmiotów usuniętych, ale nie w jakiejś określonej kolejności. Odwrotna ścieżka pętli for radzi sobie doskonale z usuwaniem elementów z tablicy. - mintedsky


Istnieją dwa główne podejścia:

  1. splatać(): anArray.splice(index, 1);

  2. kasować: delete anArray[index];

Zachowaj ostrożność, używając delete dla tablicy. Jest dobry do usuwania atrybutów obiektów, ale nie jest tak dobry dla tablic. Lepiej go użyć splice dla tablic.

Należy pamiętać, że podczas korzystania delete dla tablicy można uzyskać błędne wyniki anArray.length. Innymi słowy, delete usunie element, ale nie zaktualizuje wartości właściwości length.

Możesz także spodziewać się dziur w numerach indeksu po użyciu delete, np. możesz mieć indeksy 1,3,4,8,9,11 i długość taką, jaka była przed użyciem delete. W takim przypadku wszystkie indeksowane for pętle zawieszają się, ponieważ indeksy nie są już sekwencyjne.

Jeśli jesteś zmuszony do użycia delete z jakiegoś powodu, powinieneś użyć for each pętle, gdy trzeba przechodzić przez tablice. W rzeczywistości, jeśli to możliwe, unikaj indeksowania pętli. W ten sposób kod byłby bardziej solidny i mniej podatny na problemy z indeksami.


131
2017-12-21 11:32





Array.prototype.remByVal = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === val) {
            this.splice(i, 1);
            i--;
        }
    }
    return this;
}
//Call like
[1, 2, 3, 4].remByVal(3);

Array.prototype.remByVal = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === val) {
            this.splice(i, 1);
            i--;
        }
    }
    return this;
}

var rooms = ['hello', 'something']

rooms = rooms.remByVal('hello')

console.log(rooms)


104
2018-04-23 22:20



Nie jestem wielkim fanem tego podejścia. Jeśli w końcu korzystasz z różnych bibliotek lub frameworków, mogą się one ze sobą kolidować. - Charlie Kilian
To też zadziałało, ale ostatecznie zdecydowałem się na funkcję indexOf. Dzięki za pomoc! - Walker
Zły pomysł, zobacz ten post: stackoverflow.com/questions/948358/array-prototype-problem - MMeah
Jeśli robisz for in w macierzy masz już problem. - Zirak
Jeśli zrobisz for in na tablicach masz już większe problemy. - Rainb


Nie ma potrzeby używania indexOf lub splice. Jednak działa lepiej, jeśli chcesz tylko usunąć jedno wystąpienie elementu.

Znajdź i przenieś (przenieś):

function move(arr, val) {
  var j = 0;
  for (var i = 0, l = arr.length; i < l; i++) {
    if (arr[i] !== val) {
      arr[j++] = arr[i];
    }
  }
  arr.length = j;
}

Posługiwać się indexOf i splice (indeks):

function indexof(arr, val) {
  var i;
  while ((i = arr.indexOf(val)) != -1) {
    arr.splice(i, 1);
  }
}

Tylko do użytku splice (splatać):

function splice(arr, val) {
  for (var i = arr.length; i--;) {
    if (arr[i] === val) {
      arr.splice(i, 1);
    }
  }
}

Czas działania nodejs dla tablicy z 1000 elementów (średnio ponad 10000 przebiegów):

indeks jest około 10 razy wolniejsze niż ruszaj się. Nawet jeśli poprawi się, usuwając wywołanie indexOf w splatać działa znacznie gorzej niż ruszaj się.

Remove all occurrences:
    move 0.0048 ms
    indexof 0.0463 ms
    splice 0.0359 ms

Remove first occurrence:
    move_one 0.0041 ms
    indexof_one 0.0021 ms

82
2017-09-19 01:53



Wygląda na to, że przedstawiona tutaj metoda "move" powinna działać we wszystkich przeglądarkach, a także unikać tworzenia dodatkowej tablicy; większość innych rozwiązań ma jeden lub oba te problemy. Myślę, że ten zasługuje na więcej głosów, nawet jeśli nie wygląda na "ładny". - sockmonk