Jak mogę usunąć określony element z tablicy?

8281

Mam tablicę liczb i używam .push()metody do dodawania do niej elementów.

Czy istnieje prosty sposób na usunięcie określonego elementu z tablicy?

Szukam odpowiednika czegoś takiego jak:

array.remove(number);

Muszę użyć podstawowego JavaScript. Ramy nie są dozwolone.

Piechur
źródło

Odpowiedzi:

11869

Znajdź indexelement tablicy, którego chcesz usunąć indexOf, a następnie usuń ten indeks za pomocą splice.

Metoda splice () zmienia zawartość tablicy poprzez usunięcie istniejących elementów i / lub dodanie nowych elementów.

const array = [2, 5, 9];

console.log(array);

const index = array.indexOf(5);
if (index > -1) {
  array.splice(index, 1);
}

// array = [2, 9]
console.log(array); 

Drugim parametrem splicejest liczba elementów do usunięcia. Zauważ, że splicemodyfikuje tablicę na miejscu i zwraca nową tablicę zawierającą usunięte elementy.


Ze względu na kompletność, oto funkcje. Pierwsza funkcja usuwa tylko pojedyncze wystąpienie (tj. Usuwa pierwsze dopasowanie 5z [2,5,9,1,5,8,5]), natomiast druga funkcja usuwa wszystkie wystąpienia:

function removeItemOnce(arr, value) { 
    var index = arr.indexOf(value);
    if (index > -1) {
        arr.splice(index, 1);
    }
    return arr;
}

function removeItemAll(arr, value) {
    var i = 0;
    while (i < arr.length) {
        if(arr[i] === value) {
            arr.splice(i, 1);
        } else {
            ++i;
        }
    }
    return arr;
}
Tom Wadley
źródło
15
@Peter, tak, możesz mieć rację. W tym artykule wyjaśniono więcej i opisano sposób obejścia niezgodnych przeglądarek: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
Tom Wadley
33
@AlexandreWiechersVaz Oczywiście, że zachowuje porządek, jeśli nie, to byłby absolutnie bezwartościowy
TheZ
15
Możesz rozwiązać problem z obsługą przeglądarki IE,
15
@AdrianP. array.indexOf(testValue)na pustej tablicy będzie wynosić -1, a jeśli testujesz na to, to nie ma łączenia. Może od tego czasu odpowiedź się zmieniła.
UpTheCreek,
13
IE 7, IE8, IE9, IE10 nie są obsługiwane przez sam Microsoft, dlaczego twórcy stron internetowych powinni obsługiwać te stare przeglądarki? Po prostu pokaż powiadomienie o aktualizacji przeglądarki! support.microsoft.com/en-us/lifecycle/…
Lukas Liesis
1262

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

Aby usunąć element tablicy z indeksu i:

array.splice(i, 1);

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

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

Jeśli chcesz, aby element o indeksie ijuż nie istniał, ale nie chcesz, aby indeksy innych elementów się zmieniały:

delete array[i];
Peter Olson
źródło
333
deletenie jest poprawnym sposobem na usunięcie elementu z tablicy!
Felix Kling
71
@FelixKling Zależy, działa, jeśli chcesz, aby był array.hasOwnProperty(i)zwracany falsei miał element w tej pozycji undefined. Przyznaję jednak, że nie jest to zbyt powszechne.
Peter Olson
88
deletenie zaktualizuje długości tablicy ani nie kasuje elementu, tylko zastępuje go specjalną wartością undefined.
diosney
34
@diosney Nie wiem, co masz na myśli mówiąc, że tak naprawdę nie usuwa tego elementu. Co więcej, robi coś więcej niż zwykłe zastąpienie wartości tego indeksu undefined: usuwa zarówno indeks, jak i wartość z tablicy, tzn. Po delete array[0], "0" in arrayzwróci false.
Peter Olson,
17
@GrantGryczan Przepraszamy, nie zgadzam się. Nie widzę potrzeby, aby to usunąć. Powyższy tekst jasno wyjaśnia, co robi, i pomaga ludziom, którzy nie wiedzą, co deleterobi, aby zrozumieć, dlaczego nie działa zgodnie z oczekiwaniami.
Peter Olson,
1203

Zredagowano w październiku 2016 r

  • Zrób to proste, intuicyjne i wyraźne ( brzytwa Ockhama )
  • Zrób to niezmienne (oryginalna tablica pozostaje niezmieniona)
  • Zrób to ze standardowymi funkcjami JavaScript, jeśli twoja przeglądarka ich nie obsługuje - użyj polyfill

W tym przykładzie kodu używam funkcji „array.filter (...)”, aby usunąć niechciane elementy z tablicy. Ta funkcja nie zmienia oryginalnej tablicy i tworzy nową. Jeśli Twoja przeglądarka nie obsługuje tej funkcji (np. Internet Explorer przed wersją 9 lub Firefox przed wersją 1.5), rozważ użycie filtru wypełniającego z przeglądarki Mozilla .

Usuwanie elementu (kod ECMA-262 Edition 5, inaczej styl JavaScript w starym stylu)

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 elementu (kod ECMAScript 6)

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ŻNE Składnia funkcji strzałek ECMAScript 6 "() => {}" nie jest w ogóle obsługiwana w przeglądarce Internet Explorer, Chrome przed wersją 45, Firefox przed wersją 22 i Safari przed wersją 10. Aby użyć składni ECMAScript 6 w starych przeglądarkach, możesz użyć BabelJS .


Usuwanie wielu elementów (kod ECMAScript 7)

Dodatkową zaletą tej metody jest to, że możesz usunąć wiele 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ŻNE Funkcja „array.includes (...)” nie jest w ogóle obsługiwana w przeglądarce Internet Explorer, Chrome przed wersją 47, Firefox przed wersją 43, Safari przed wersją 9 i Edge przed wersją 14, więc tutaj jest polifill z Mozilli .

Usuwanie wielu elementów (być może w przyszłości)

Jeśli propozycja „This-Binding Syntax” zostanie kiedykolwiek zaakceptowana, będziesz mógł to zrobić:

// 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

ujeenator
źródło
6
ale czasami chcemy usunąć element z oryginalnej tablicy (niezmiennej), na przykład tablica używana w Angular 2 * ngF Dla dyrektywy
Ravinder Payal
43
Lepsze niż przyjęte rozwiązanie, ponieważ nie zakłada ono tylko jednego wystąpienia dopasowania, a niezmienność jest lepsza
Greg
13
filtermusi być jednak znacznie wolniejszy dla dużej tablicy?
Nathan
3
Jaki jest sens niezmienności, jeśli użyłeś przypisania tej samej zmiennej w swoich przykładach? :)
różowe
12
To świetna odpowiedź. Splice to wyspecjalizowana funkcja do mutowania bez filtrowania. filtermoże mieć mniejszą wydajność, ale jest to bezpieczniejszy i lepszy kod. Ponadto możesz filtrować według indeksu, podając drugi argument w lambda:arr.filter((x,i)=>i!==2)
Matthew
449

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

Jeśli chcesz puste miejsce, usuwanie jest w porządku:

delete array[index];

Jeśli nie, powinieneś użyć metody łączenia :

array.splice(index, 1);

A jeśli potrzebujesz wartości tego elementu, możesz po prostu zapisać zwrócony element tablicy:

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

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

A jeśli nie znasz indeksu przedmiotu, możesz go użyć array.indexOf(item)(w if()celu uzyskania jednego przedmiotu lub w while()celu uzyskania wszystkich). array.indexOf(item)zwraca indeks lub -1, jeśli nie znaleziono. 

xavierm02
źródło
25
deletenie jest poprawnym sposobem na usunięcie elementu z tablicy !!
Progo,
16
Jeśli chcesz „opróżnić miejsce”, użyj array[index] = undefined;. Używanie deletezniszczy optymalizację.
Bergi,
4
@Jakub bardzo dobrą wiadomość, ponieważ aby zrozumieć, że straciłem dużo czasu i że mój kod aplikacji jest w jakiś sposób uszkodzony ...
Pascal
Ostatni akapit z wyjaśnieniem tego, co otrzymujesz z indexOf, był bardzo pomocny
A. D'Alfonso
277

Znajomy miał problemy z programem Internet Explorer 8 i pokazał mi, co zrobił. Powiedziałem mu, że to źle, a on powiedział mi, że otrzymał odpowiedź tutaj. Bieżąca najwyższa odpowiedź nie będzie działać we wszystkich przeglądarkach (na przykład Internet Explorer 8) i usunie tylko pierwsze wystąpienie 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ść będą się zmieniać w miarę usuwania elementów) i usuwa element, jeśli zostanie znaleziony. Działa we wszystkich przeglądarkach.

Ben Lesh
źródło
11
@sroes nie powinno tak być, ponieważ pętla zaczyna się od i = arr.length -1lub i--sprawia, że ​​jest taka sama jak indeks maksymalny. arr.lengthjest tylko wartością początkową dla i. i--zawsze będzie zgodne z prawdą (i zmniejsza się o 1 przy każdej operacji pętli), dopóki nie 0wyrówna się (wartość falsy), a następnie pętla się zatrzyma.
gmajivu
1
Druga funkcja jest raczej nieefektywna. Przy każdej iteracji „indexOf” rozpocznie wyszukiwanie od początku tablicy.
ujeenator
3
@AmberdeBlack, w kolekcji z więcej niż 1 wystąpieniem elementu , znacznie lepiej zamiast tego wywołać metodę filtruarr.filter(function (el) { return el !== item }) , unikając konieczności wielokrotnego mutowania tablicy. To zużywa nieco więcej pamięci, ale działa znacznie wydajniej, ponieważ wymaga mniej pracy.
Eugene Kuzmenko
1
@AlJey, jest dostępny tylko w IE9 +. Nadal istnieje szansa, że ​​to nie zadziała.
ujeenator
1
Ta odpowiedź działała dla mnie, ponieważ potrzebowałem kilku elementów usuniętych, ale nie w określonej kolejności. Postępy wstecz w pętli for doskonale radzą sobie z usuwaniem elementów z tablicy.
mintedsky
172

Istnieją dwa główne podejścia:

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

  2. usuń :delete anArray[index];

Zachowaj ostrożność, gdy używasz delete dla tablicy. Jest dobry do usuwania atrybutów obiektów, ale nie tak dobrze do tablic. Lepiej jest używać splicedo tablic.

Pamiętaj, że jeśli użyjesz deletetablicy, możesz uzyskać błędne wyniki anArray.length. Innymi słowy, deleteusunąłby element, ale nie zaktualizowałby wartości właściwości length.

Możesz także spodziewać się, że po użyciu delete będą występować dziury w numerach indeksów, np. Możesz mieć indeksy 1, 3, 4, 8, 9 i 11 oraz długość taką, jaka była przed użyciem delete. W takim przypadku wszystkie indeksowane forpętle uległyby awarii, ponieważ indeksy nie są już sekwencyjne.

Jeśli deletez jakiegoś powodu jesteś zmuszony do używania , powinieneś używać for eachpętli, gdy potrzebujesz zapętlić tablice. W rzeczywistości for, jeśli to możliwe , zawsze unikaj używania indeksowanych pętli. W ten sposób kod byłby bardziej niezawodny i mniej podatny na problemy z indeksami.

Sasa
źródło
144
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)

Zirak
źródło
14
Nie jestem wielkim fanem tego podejścia. Jeśli użyjesz różnych bibliotek lub frameworków, mogą się one ze sobą sprzeczne.
Charlie Kilian,
10
Zły pomysł, zobacz ten post: stackoverflow.com/questions/948358/array-prototype-problem
MMeah
10
Jeśli robisz for intablicę, masz już problem.
Zirak
2
jeśli robisz for intablice, masz już większe problemy.
Rainb
użyj Object.defineProperty stackoverflow.com/a/35518127/3779853 i możesz zacząć.
phil294
105

Nie ma potrzeby używania indexOflub splice. Jednak działa lepiej, jeśli chcesz usunąć tylko 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;
}

Użyj indexOfi splice(indexof):

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

Używaj tylko splice(łączenie):

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

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

indexof jest około 10 razy wolniejszy niż ruch . Nawet jeżeli poprawione przez usunięcie wywołanie indexOfw splice wykonuje znacznie gorsze niż ruch .

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
slosd
źródło
5
Wygląda na to, że przedstawiona tutaj metoda „move” powinna działać we wszystkich przeglądarkach, a także pozwala uniknąć tworzenia dodatkowej tablicy; większość innych rozwiązań ma jeden lub oba z tych problemów. Myślę, że ten zasługuje na znacznie więcej głosów, nawet jeśli nie wygląda na „ładny”.
sockmonk
73

To daje predykat zamiast wartości.

UWAGA: zaktualizuje podaną tablicę i zwróci zmienione wiersze.

Stosowanie

var removed = helper.removeOne(arr, row => row.id === 5 );

var removed = helper.remove(arr, row => row.name.startsWith('BMW'));

Definicja

var helper = {

    // Remove and return the first occurrence

    removeOne: function(array, predicate) {
        for (var i = 0; i < array.length; i++) {
            if (predicate(array[i])) {
                return array.splice(i, 1);
            }
        }
    },

    // Remove and return all occurrences

    remove: function(array, predicate) {
        var removed = [];

        for (var i = 0; i < array.length;) {

            if (predicate(array[i])) {
                removed.push(array.splice(i, 1));
                continue;
            }
            i++;
        }
        return removed;
    }
};
amd
źródło
Nie wiem, czy potrzebujesz czeku -1 (i> -1). Myślę też, że te funkcje działają bardziej jak filtrowanie niż usuwanie. Jeśli przekażesz row.id === 5, wynikiem będzie tablica o tylko id 5, więc robi to odwrotnie niż w przypadku remove. Ładnie wyglądałoby to w ES2015: var result = ArrayHelper.remove (myArray, row => row.id === 5);
What Be Cool
@WhatWouldBeCool ta funkcja modyfikuje oryginalną tablicę i zwraca usunięty element zamiast kopiowania wyniku do nowej tablicy
am
68

Możesz to łatwo zrobić za pomocą metody filtrowania :

function remove(arrOriginal, elementToRemove){
    return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log(remove([1, 2, 1, 0, 3, 1, 4], 1));

To usuwa wszystkie elementy z tablicy, a także działa szybciej niż kombinacja slicei indexOf.

Salvador Dali
źródło
3
Czy masz źródło, że jest to szybsze?
user3711421
2
Niezłe rozwiązanie. Ale, jak
wskazałeś
1
@ user3711421 dzieje się tak, ponieważ po prostu plaster i indexOf nie robi tego, co chce „usunąć określony element”. Usuwa element tylko raz, to usuwa określony element bez względu na to, ile ich masz
Salvador Dali
66

John Resig opublikował dobre wdrożenie :

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

Jeśli nie chcesz rozszerzać obiektu globalnego, możesz zamiast tego zrobić coś takiego:

// Array Remove - By John Resig (MIT Licensed)
Array.remove = function(array, from, to) {
    var rest = array.slice((to || from) + 1 || array.length);
    array.length = from < 0 ? array.length + from : from;
    return array.push.apply(array, rest);
};

Ale głównym powodem, dla którego to publikuję, jest ostrzeżenie użytkowników przed alternatywną implementacją sugerowaną w komentarzach na tej stronie (14 grudnia 2007):

Array.prototype.remove = function(from, to){
  this.splice(from, (to=[0,from||1,++to-from][arguments.length])<0?this.length+to:to);
  return this.length;
};

Z początku wydaje się, że działa dobrze, ale podczas bolesnego procesu odkryłem, że zawodzi przy próbie usunięcia drugiego do ostatniego elementu w tablicy. Na przykład, jeśli masz tablicę 10-elementową i próbujesz usunąć 9 element za pomocą:

myArray.remove(8);

Otrzymujesz 8-elementową tablicę. Nie wiem dlaczego, ale potwierdziłem, że oryginalna implementacja Johna nie ma tego problemu.

zrozumiałem
źródło
Właśnie nauczyłem się na Object.prototype.hasOwnPropertywłasnej skórze, dlaczego warto używać zawsze ¬¬
Davi Fiamenghi
64

Underscore.js może być wykorzystywany do rozwiązywania problemów z wieloma przeglądarkami. Używa wbudowanych metod przeglądarki, jeśli są obecne. Jeśli są nieobecne, jak w przypadku starszych wersji Internet Explorera, używa własnych metod niestandardowych.

Prosty przykład usuwania elementów z tablicy (ze strony internetowej):

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]
vatsal
źródło
choć elegancki i zwięzły, OP wyraźnie wspomniał tylko o rdzeniu JS
EigenFool
64

Możesz użyć ES6. Na przykład, aby w tym przypadku usunąć wartość „3”:

var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
console.log(newArray);

Wynik :

["1", "2", "4", "5", "6"]
rajat44
źródło
4
Ta odpowiedź jest dobra, ponieważ tworzy kopię oryginalnej tablicy, zamiast bezpośrednio modyfikować oryginał.
Claudio Holanda
Uwaga: Array.prototype.filter to ECMAScript 5.1 (bez IE8). dla bardziej szczegółowych rozwiązań: stackoverflow.com/a/54390552/8958729
Chang
54

Jeśli chcesz usunąć nową tablicę z usuniętymi pozycjami, zawsze możesz usunąć określony element i odfiltrować tablicę. Może potrzebować rozszerzenia obiektu tablicy dla przeglądarek, które nie implementują metody filtrowania, ale w dłuższej perspektywie jest to łatwiejsze, ponieważ wszystko, co robisz, to:

var my_array = [1, 2, 3, 4, 5, 6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));

Powinien zostać wyświetlony [1, 2, 3, 4, 6].

Loupax
źródło
45

Sprawdź ten kod. Działa w każdej większej przeglądarce .

remove_item = function (arr, value) {
    var b = '';
    for (b in arr) {
        if (arr[b] === value) {
            arr.splice(b, 1);
            break;
        }
    }
    return arr;
}

Wywołaj tę funkcję

remove_item(array,value);
Ekramul Hoque
źródło
4
@RolandIllig Z wyjątkiem użycia pętli for ini faktu, że skrypt można zatrzymać wcześniej, zwracając bezpośrednio wynik z pętli. Pozytywne opinie są uzasadnione;)
yckart
1
Jest to doskonałe podejście do małych tablic. Działa w każdej przeglądarce, używa minimalnego i intuicyjnego kodu i bez żadnych dodatkowych skomplikowanych ram, podkładek ani wypełniaczy.
Beejor,
Powinienem również powtórzyć komentarz yckart, który for( i = 0; i < arr.length; i++ )byłby lepszym podejściem, ponieważ zachowuje dokładne wskaźniki w stosunku do dowolnej kolejności, w której przeglądarka zdecyduje się przechowywać elementy (z for in). Takie postępowanie pozwala również uzyskać indeks tablicy wartości, jeśli jest potrzebny.
Beejor,
41

Możesz użyć lodash _.pull ( mutate array), _.pullAt ( mutate array) lub _. bez ( mutate array),

var array1 = ['a', 'b', 'c', 'd']
_.pull(array1, 'c')
console.log(array1) // ['a', 'b', 'd']

var array2 = ['e', 'f', 'g', 'h']
_.pullAt(array2, 0)
console.log(array2) // ['f', 'g', 'h']

var array3 = ['i', 'j', 'k', 'l']
var newArray = _.without(array3, 'i') // ['j', 'k', 'l']
console.log(array3) // ['i', 'j', 'k', 'l']
Chun Yang
źródło
2
To nie jest podstawowy JS, jak wymagał PO, prawda?
Some-non-descript-user
12
@ Some-non-descript-user Masz rację. Ale wielu użytkowników takich jak ja przybywa tutaj, szukając ogólnej odpowiedzi nie tylko dla OP.
Chun Yang,
@ChunYang Masz absolutną rację. Już używam lodash, dlaczego nie użyć go, jeśli oszczędza czas.
int-i
38

ES6 i bez mutacji: (październik 2016 r.)

const removeByIndex = (list, index) =>
      [
        ...list.slice(0, index),
        ...list.slice(index + 1)
      ];
         
output = removeByIndex([33,22,11,44],1) //=> [33,11,44]
      
console.log(output)

Abdennour TOUMI
źródło
Dlaczego więc nie skorzystać filter? array.filter((_, index) => index !== removedIndex);.
user4642212
@ user4642212 masz rację! Podobał mi się również podkreślenie stylu Golang
Abdennour TOUMI
36

Usunięcie określonego elementu / łańcucha z tablicy można wykonać w jednej linijce:

theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);

gdzie:

theArray : tablica, z której chcesz usunąć coś konkretnego

stringToRemoveFromArray : ciąg, który chcesz usunąć, a 1 to liczba elementów, które chcesz usunąć.

UWAGA : Jeśli „stringToRemoveFromArray” nie znajduje się w tablicy, spowoduje to usunięcie ostatniego elementu tablicy.

Zawsze dobrą praktyką jest sprawdzenie, czy element istnieje w tablicy przed jego usunięciem.

if (theArray.indexOf("stringToRemoveFromArray") >= 0){
   theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
}

Jeśli masz dostęp do nowszych wersji Ecmascript na komputerach swojego klienta (OSTRZEŻENIE, może nie działać na starszych stacjach):

var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');

Gdzie „3” to wartość, którą chcesz usunąć z tablicy. Tablica stałaby się wtedy:['1','2','4','5','6']

Max Alexander Hanna
źródło
To była odpowiedź, która działała dla mnie, gdy próbowałem zaktualizować tablicę na podstawie przełączania przycisku opcji.
jdavid05
4
Uwaga, jeśli "stringToRemoveFromArray"nie znajduje się w tablicy, spowoduje to usunięcie ostatniego elementu tablicy.
Fusion,
35

Oto kilka sposobów na usunięcie elementu z tablicy za pomocą JavaScript .

Wszystkie opisane metody nie mutują oryginalnej tablicy , a zamiast tego tworzą nową.

Jeśli znasz indeks przedmiotu

Załóżmy, że masz tablicę i chcesz usunąć element na miejscu i.

Jedną z metod jest użycie slice():

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i).concat(items.slice(i+1, items.length))

console.log(filteredItems)

slice()tworzy nową tablicę z otrzymanymi indeksami. Po prostu tworzymy nową tablicę, od początku do indeksu, który chcemy usunąć, i konkatenujemy kolejną tablicę od pierwszej pozycji po tej, którą usunęliśmy do końca tablicy.

Jeśli znasz wartość

W tym przypadku jedną z dobrych opcji jest użycie filter(), które oferuje bardziej deklaratywne podejście:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)

console.log(filteredItems)

Wykorzystuje to funkcje strzałek ES6. Możesz użyć tradycyjnych funkcji do obsługi starszych przeglądarek:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
  return item !== valueToRemove
})

console.log(filteredItems)

lub możesz użyć Babel i przetransportować kod ES6 z powrotem do ES5, aby uczynić go bardziej zrozumiałym dla starych przeglądarek, a jednocześnie napisać nowoczesny kod JavaScript w swoim kodzie.

Usuwanie wielu elementów

Co jeśli zamiast jednego elementu chcesz usunąć wiele elementów?

Znajdźmy najprostsze rozwiązanie.

Według indeksu

Możesz po prostu utworzyć funkcję i usuwać elementy szeregowo:

const items = ['a', 'b', 'c', 'd', 'e', 'f']

const removeItem = (items, i) =>
  items.slice(0, i-1).concat(items.slice(i, items.length))

let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]

console.log(filteredItems)

Według wartości

Możesz wyszukać włączenie w ramach funkcji oddzwaniania:

const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]

console.log(filteredItems)

Unikaj mutowania oryginalnej tablicy

splice()(nie mylić z slice()) mutuje oryginalną tablicę i należy tego unikać.

(pierwotnie opublikowane na https://flaviocopes.com/how-to-remove-item-from-array/ )

Flavio Copes
źródło
34

OK, na przykład masz tablicę poniżej:

var num = [1, 2, 3, 4, 5];

I chcemy usunąć numer 4. Możesz po prostu użyć poniższego kodu:

num.splice(num.indexOf(4), 1); // num will be [1, 2, 3, 5];

Jeśli ponownie używasz tej funkcji, piszesz funkcję wielokrotnego użytku, która zostanie dołączona do natywnej funkcji tablicy, jak poniżej:

Array.prototype.remove = Array.prototype.remove || function(x) {
  const i = this.indexOf(x);
  if(i===-1)
      return;
  this.splice(i, 1); // num.remove(5) === [1, 2, 3];
}

Ale co powiesz na to, że zamiast tego masz poniżej tablicę z kilkoma [5] sami w tablicy?

var num = [5, 6, 5, 4, 5, 1, 5];

Potrzebujemy pętli, aby je wszystkie sprawdzić, ale łatwiejszym i bardziej wydajnym sposobem jest użycie wbudowanych funkcji JavaScript, więc zamiast tego piszemy funkcję, która używa filtra takiego jak poniżej:

const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) // Return [1, 2, 3, 4, 6]

Istnieją również biblioteki stron trzecich, które pomagają ci to zrobić, takie jak Lodash lub Underscore. Aby uzyskać więcej informacji, spójrz na lodash _.pull, _.pullAt lub _. bez.

Alireza
źródło
Jest mała literówka. Proszę popraw. this.splice(num.indexOf(x), 1);=>this.splice(this.indexOf(x), 1);
TheGwa
Nie rozszerzaj wbudowanych skryptów (dołącz funkcje do Array.prototype) w JavaScript. Jest to powszechnie uważane za złą praktykę.
aikeru
Zgadzam się, że nie jest to najlepsza rzecz na świecie, ale w tym przypadku, jak możesz przekazać to do funkcji?
Alireza,
Powinieneś sprawdzić indeks. Jeśli indeks = -1, splatanie (-1,1) usunie ostatni element
Richard Chan
29

Jestem całkiem nowy w JavaScript i potrzebowałem tej funkcjonalności. Po prostu napisałem to:

function removeFromArray(array, item, index) {
  while((index = array.indexOf(item)) > -1) {
    array.splice(index, 1);
  }
}

Kiedy chcę go użyć:

//Set-up some dummy data
var dummyObj = {name:"meow"};
var dummyArray = [dummyObj, "item1", "item1", "item2"];

//Remove the dummy data
removeFromArray(dummyArray, dummyObj);
removeFromArray(dummyArray, "item2");

Wyjście - zgodnie z oczekiwaniami. [„item1”, „item1”]

Możesz mieć inne potrzeby niż ja, więc możesz łatwo modyfikować je, aby je dopasować. Mam nadzieję, że to komuś pomoże.

sofiax
źródło
1
Będzie to miało okropne zachowanie, jeśli twoja tablica jest naprawdę długa i zawiera kilka instancji tego elementu. Metoda indexOf macierzy zacznie się na początku za każdym razem, więc twój koszt wyniesie O (n ^ 2).
Zag
@Zag: Ma nazwę: Algorytm malarza Shlemiela
Peter Mortensen
27

Jeśli masz w tablicy złożone obiekty, możesz użyć filtrów? W sytuacjach, gdy $ .inArray lub array.splice nie jest tak łatwy w użyciu. Zwłaszcza jeśli obiekty są być może płytkie w tablicy.

Np. Jeśli masz obiekt z polem Id i chcesz go usunąć z tablicy:

this.array = this.array.filter(function(element, i) {
    return element.id !== idToRemove;
});
flurdy
źródło
Tak lubię to robić. Korzystając z funkcji strzałki, może być jednostronny. Jestem ciekawa wydajności. Również nic nie warte, że to zastępuje tablicę. Każdy kod z odniesieniem do starej tablicy nie zauważy zmiany.
joeytwiddle
27

Chcę odpowiedzieć na podstawie ECMAScript 6 . Załóżmy, że masz tablicę jak poniżej:

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

Jeśli chcesz usunąć ze specjalnego indeksu, takiego jak 2, napisz poniższy kod:

arr.splice(2, 1); //=> arr became [1,2,4]

Ale jeśli chcesz usunąć specjalny element, taki jak 3i nie znasz jego indeksu, wykonaj poniższe czynności:

arr = arr.filter(e => e !== 3); //=> arr became [1,2,4]

Wskazówka : użyj funkcji strzałki do wywołania zwrotnego filtra, chyba że otrzymasz pustą tablicę.

AmerllicA
źródło
25

Aktualizacja: Ta metoda jest zalecana tylko wtedy, gdy nie można używać ECMAScript 2015 (wcześniej znanej jako ES6). Jeśli możesz z niego skorzystać, inne odpowiedzi tutaj zapewniają znacznie bardziej odpowiednie implementacje.


Ta lista rozwiąże Twój problem, a także usunie wszystkie wystąpienia argumentu zamiast tylko 1 (lub określonej wartości).

Array.prototype.destroy = function(obj){
    // Return null if no objects were found and removed
    var destroyed = null;

    for(var i = 0; i < this.length; i++){

        // Use while-loop to find adjacent equal objects
        while(this[i] === obj){

            // Remove this[i] and store it within destroyed
            destroyed = this.splice(i, 1)[0];
        }
    }

    return destroyed;
}

Stosowanie:

var x = [1, 2, 3, 3, true, false, undefined, false];

x.destroy(3);         // => 3
x.destroy(false);     // => false
x;                    // => [1, 2, true, undefined]

x.destroy(true);      // => true
x.destroy(undefined); // => undefined
x;                    // => [1, 2]

x.destroy(3);         // => null
x;                    // => [1, 2]
zykadelic
źródło
25

Wydajność

Dzisiaj (2019-12-09) Przeprowadzam testy wydajnościowe systemu macOS 10.13.6 (High Sierra) dla wybranych rozwiązań. Wyświetlam delete(A), ale nie używam go w porównaniu z innymi metodami, ponieważ pozostawił puste miejsce w tablicy.

Wnioski

  • najszybszym rozwiązaniem jest array.splice(C) (z wyjątkiem Safari dla małych tablic, w których jest drugi raz)
  • w przypadku dużych tablic array.slice+splice(H) jest najszybszym niezmiennym rozwiązaniem dla przeglądarek Firefox i Safari; Array.from(B) jest najszybszy w Chrome
  • modyfikowalne rozwiązania są zwykle 1,5x-6x szybsze niż niezmienne
  • w przypadku małych stolików w Safari, zaskakująco, zmienne rozwiązanie (C) jest wolniejsze niż niezmienne rozwiązanie (G)

Detale

W testach usuwam środkowy element z tablicy na różne sposoby. Rozwiązania A, C są na miejscu. Rozwiązania B, D, E, F, G, H są niezmienne.

Wyniki dla tablicy z 10 elementami

Wpisz opis zdjęcia tutaj

W Chrome array.splice(C) jest najszybszym rozwiązaniem na miejscu. array.filter(D) jest najszybszym stały roztwór. Najwolniejszy to array.slice(F). Możesz wykonać test na swoim komputerze tutaj .

Wyniki dla tablicy z 1.000.000 elementów

Wpisz opis zdjęcia tutaj

W Chrome array.splice(C) jest najszybszym rozwiązaniem na miejscu ( delete(C) jest podobne szybko - ale pozostawił puste miejsce w tablicy (więc nie wykonuje „pełnego usunięcia”)). array.slice-splice(H) jest najszybszym stały roztwór. Najwolniejszy to array.filter(D i E). Możesz wykonać test na swoim komputerze tutaj .

Porównanie przeglądarek: Chrome v78.0.0, Safari v13.0.4 i Firefox v71.0.0

Wpisz opis zdjęcia tutaj

Kamil Kiełczewski
źródło
24

Nigdy nie powinieneś mutować swojej tablicy. Jest to sprzeczne z funkcjonalnym wzorcem programowania. Możesz utworzyć nową tablicę bez odwoływania się do tablicy, którą chcesz zmienić przy użyciu metody ECMAScript 6 filter;

var myArray = [1, 2, 3, 4, 5, 6];

Załóżmy, że chcesz usunąć 5z tablicy, możesz po prostu zrobić to w następujący sposób:

myArray = myArray.filter(value => value !== 5);

To da ci nową tablicę bez wartości, którą chciałbyś usunąć. Rezultatem będzie:

 [1, 2, 3, 4, 6]; // 5 has been removed from this array

Dla lepszego zrozumienia możesz przeczytać dokumentację MDN na Array.filter .

Adeel Imran
źródło
21

Bardziej nowoczesne podejście ECMAScript 2015 (wcześniej znane jako Harmony lub ES 6). Dany:

const items = [1, 2, 3, 4];
const index = 2;

Następnie:

items.filter((x, i) => i !== index);

Wydajność:

[1, 2, 4]

Możesz użyć Babel i usługi wypełniania, aby upewnić się, że jest dobrze obsługiwana w różnych przeglądarkach.

bjfletcher
źródło
4
Zauważ, że .filterzwraca nową tablicę, która nie jest dokładnie taka sama jak usunięcie elementu z tej samej tablicy. Zaletą tego podejścia jest to, że można łączyć ze sobą metody tablic. np .:[1,2,3].filter(n => n%2).map(n => n*n) === [ 1, 9 ]
CodeOcelot
Świetnie, jeśli mam 600 tys. Elementów w tablicy i chcę usunąć pierwsze 50 tys., Czy możesz sobie wyobrazić tę powolność? To nie jest rozwiązanie, potrzebna jest funkcja, która po prostu usuwa elementy i nic nie zwraca.
dev1223
@Seraph W tym celu prawdopodobnie będziesz chciał użyć splicelub slice.
bjfletcher
@bjfletcher To jeszcze lepiej, w procesie usuwania, po prostu przydziel 50K elementów i wyrzuć je gdzieś. (z wycięciem elementów 550K, ale bez wyrzucania ich z okna).
dev1223
Wolałbym odpowiedź bjfletchera, która może być tak krótka jak items= items.filter(x=>x!=3). Poza tym PO nie stwierdził żadnego wymogu dla dużego zestawu danych.
kursuje
21

Masz od 1 do 9 w tablicy i chcesz usunąć 5. Użyj poniższego kodu:

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return m !== 5;
});

console.log("new Array, 5 removed", newNumberArray);


Jeśli chcesz wiele wartości. Przykład: - 1,7,8

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var newNumberArray = numberArray.filter(m => {
  return (m !== 1) && (m !== 7) && (m !== 8);
});

console.log("new Array, 1,7 and 8 removed", newNumberArray);


Jeśli chcesz usunąć wartość tablicy z tablicy. Przykład: [3,4,5]

var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var removebleArray = [3,4,5];

var newNumberArray = numberArray.filter(m => {
    return !removebleArray.includes(m);
});

console.log("new Array, [3,4,5] removed", newNumberArray);

Zawiera obsługiwaną przeglądarkę to link .

Thilina Sampath
źródło
19

Wiem, że jest już wiele odpowiedzi, ale wiele z nich wydaje się nadmiernie komplikować problem. Oto prosty, rekurencyjny sposób usuwania wszystkich instancji klucza - wywołuje siebie, dopóki indeks nie zostanie znaleziony. Tak, działa tylko w przeglądarkach indexOf, ale jest prosty i można go łatwo wypełnić.

Funkcja samodzielna

function removeAll(array, key){
    var index = array.indexOf(key);

    if(index === -1) return;

    array.splice(index, 1);
    removeAll(array,key);
}

Metoda prototypowa

Array.prototype.removeAll = function(key){
    var index = this.indexOf(key);

    if(index === -1) return;

    this.splice(index, 1);
    this.removeAll(key);
}
wharding28
źródło
Tylko uwaga: 1 zastrzeżenie dotyczące tej metody może spowodować przepełnienie stosu. Jeśli nie pracujesz z ogromnymi tablicami, nie powinieneś mieć problemu.
wharding28
Ale dlaczego powrót w środku? Jest to w rzeczywistości deklaracja goto.
Peter Mortensen,
18

Możesz wykonać pętlę wsteczną, aby upewnić się, że indeksy nie zostaną zepsute, jeśli istnieje wiele wystąpień elementu.

var myElement = "chocolate";
var myArray = ['chocolate', 'poptart', 'poptart', 'poptart', 'chocolate', 'poptart', 'poptart', 'chocolate'];

/* Important code */
for (var i = myArray.length - 1; i >= 0; i--) {
    if (myArray[i] == myElement) myArray.splice(i, 1);
}

Demo na żywo

Jeff Noel
źródło