Как удалить элемент массива в TypeScript?

408

У меня есть массив, который я создал в TypeScript, и у него есть свойство, которое я использую в качестве ключа. Если у меня есть этот ключ, как я могу удалить предмет из него?

Тим Алмонд
источник

Ответы:

642

Так же, как и в JavaScript.

delete myArray[key];

Обратите внимание, что это устанавливает элемент в undefined.

Лучше использовать Array.prototype.spliceфункцию:

const index = myArray.indexOf(key, 0);
if (index > -1) {
   myArray.splice(index, 1);
}
blorkfish
источник
8
Вы можете добавить тип к этому! var index: number = myArray.indexOf(key, 0);
CorayThan
17
@CorayThan Конечно, это будет неявно напечатано как indexOfвозвращает a number?
Крис
5
@Chris Хотя в этом простом случае это очевидно, он может помочь вам быстрее диагностировать ошибки, если вы явно определите тип для каждой переменной. Вы уже используете indexболее одного раза, и одно из этих мест ( splice) хочет увидеть число, или вы получите ошибку. В настоящее время компилятор не может помешать вам делать ошибки там
Йохем Куиджперс
33
@blorkfish хорошо упомянуть, что если у вас есть список объектов, вы можете использовать var index = myArray.findIndex(x => x.prop==key.prop);.
Франциско Кабрал
6
@ Cirelli94 - вы отвечаете на более старую ветку, но ответ на ваш вопрос заключается в том, что удаление элемента массива не меняет его длину и не переиндексирует массив. Поскольку массивы являются объектами в JavaScript, delete myArr[2]буквально удаляет свойство 2 из myArr, которое также отличается myArr[2] = undefined. Мораль этой истории - просто использовать spliceдля этой задачи, потому что это безопасный способ получить желаемый эффект, не путая побочные эффекты.
winglerw28
200

Если массив является типом объектов, то самый простой способ

let foo_object // Item to remove
this.foo_objects = this.foo_objects.filter(obj => obj !== foo_object);
Малик Шахзад
источник
20
Это ничего не удаляет, оно просто фильтрует. Если список действительно нужно изменить, это не так.
user573434
6
@ user573434 да, вы правы, как видно из названия. Но это простой подход, если вы хотите удалить объект при удачном вызове API api и т. Д.
Малик Шахзад,
3
Это отлично сработало для меня с массивом объектов без уникального свойства ключа. @ user573434 метод filter возвращает новый массив без фильтруемого объекта, поэтому результирующий массив действительно удаляет объект.
Джейсон
6
Я думаю, чтобы вернуть его как объект, вы должны сделать этоthis.foo_objects = this.foo_objects.filter(obj => obj !== foo_object)[0];
Roel
1
Это работает. просто внимательно прочитайте 2-ю строку. он делает фильтр с obj! = foo_object. и присваивает его исходной переменной, тем самым заменяя исходный массив одним минус фильтрованный объект foo_object. использовал его с массивом объектов с идентификатором. deleteById(id: string) { this.data = this.data.filter(d => d.id !== id); }Только одно слово предупреждения, если идентификаторы не являются уникальными, вы удалите все с тем жеid
Markus
74

С ES6 вы можете использовать этот код:

removeDocument(doc){
   this.documents.forEach( (item, index) => {
     if(item === doc) this.documents.splice(index,1);
   });
}
Idak
источник
1
Лучшее решение для удаления без изменения ссылки на массив И с возможностью реализации конкретного алгоритма равенства
Сид
1
Лучший ответ нашли
Gvs Akhil
1
Лучший ответ при использовании ES6
Натан Бек
2
Вы также можете использовать: this.documents.forEach ((item, index, array) => {if (item === doc) array.splice (index, 1);}); Который может быть намного чище, особенно при работе с вложенными массивами.
CGundlach
20

Это мое решение для этого:

onDelete(id: number) {
    this.service.delete(id).then(() => {
        let index = this.documents.findIndex(d => d.id === id); //find index in your array
        this.documents.splice(index, 1);//remove element from array
    });

    event.stopPropagation();
}
Butsaty
источник
Что хорошо в этом решении, так это то, что оно будет работать, даже если объектное равенство не сможет идентифицировать два объекта как равные.
Брэд Джонсон
18

Вы можете использовать spliceметод в массиве для удаления элементов.

например, если у вас есть массив с именем, arrиспользуйте следующее:

arr.splice(2, 1);

поэтому здесь элемент с индексом 2 будет отправной точкой, а аргумент 2 определит, сколько элементов будет удалено.

Если вы хотите удалить последний элемент названного массива, arrсделайте это:

arr.splice(arr.length-1, 1);

Это вернет arr с последним удаленным элементом.

Пример:

var arr = ["orange", "mango", "banana", "sugar", "tea"];
arr.splice(arr.length-1, 1)
console.log(arr); // return ["orange", "mango", "banana", "sugar"]
акаш венугопал
источник
1
Просто FYI, метод соединения модифицирует массив (поэтому в этом случае удаляет последний элемент) и возвращает удаленный элемент (ы), а не сам массив.
CGundlach
2
На самом деле это должен быть arr.splice (arr.length-1,1) для удаления последнего элемента.
Стив Ин CO
15

пусть отделы это массив. Вы хотите удалить элемент из этого массива.

departments: string[] = [];

 removeDepartment(name: string): void {
    this.departments = this.departments.filter(item => item != name);
  }
Абдус Салам Азад
источник
8

Вот простой вкладыш для удаления объекта по свойству из массива объектов.

delete this.items[this.items.findIndex(item => item.item_id == item_id)];

или

this.items = this.items.filter(item => item.item_id !== item.item_id);
Джейми Армор
источник
1
Проблема с первым решением состоит в том, что delete удаляет элемент, но размер массива остается таким же, как и до обнаружения. Во втором решении у нас будет новый объект, поэтому, если у нас есть зависимость от spme, мы теряем его. Сплайс (который находится в верхнем ответе) не имеет этого эффекта.
Кристиан
Спасибо что подметил это. Я думаю, что в моем случае использования я еще не обнаружил это. Хорошо
Jamie Armor
5

Ответ, используя оператор распространения TypeScript (...)

// Your key
const key = 'two';

// Your array
const arr = [
    'one',
    'two',
    'three'
];

// Get either the index or -1
const index = arr.indexOf(key); // returns 0


// Despite a real index, or -1, use spread operator and Array.prototype.slice()    
const newArray = (index > -1) ? [
    ...arr.slice(0, index),
    ...arr.slice(index + 1)
] : arr;
Джошуа Майкл Вагонер
источник
5

Еще одно решение с использованием Typescript:

let updatedArray = [];
for (let el of this.oldArray) {
    if (el !== elementToRemove) {
        updated.push(el);
    }
}
this.oldArray = updated;
Шиллинг Павел
источник
Хотя это и решает поставленную проблему, его выполнение обходится дорого из-за создания нового массива и зацикливания на оригинале. Выполнение такого рода операций с огромным массивом может привести к нежелательным побочным эффектам, таким как усиление работы мобильных батарей, долгое ожидание, рывок и т. Д.
Джесси,
1

Используйте это, если вам нужно удалить данный объект из массива, и вы хотите быть уверены в следующем:

  • список не переинициализирован
  • длина массива правильно обновлена
    const objWithIdToRemove;
    const objIndex = this.objectsArray.findIndex(obj => obj.id === objWithIdToRemove);
    if (objIndex > -1) {
      this.objectsArray.splice(objIndex, 1);
    }
Раду Лину
источник
0

Просто хотел добавить метод расширения для массива.

interface Array<T> {
      remove(element: T): Array<T>;
    }

    Array.prototype.remove = function (element) {
      const index = this.indexOf(element, 0);
      if (index > -1) {
        return this.splice(index, 1);
      }
      return this;
    };
supernerd
источник