Удаление элементов массива в JavaScript - удаление против сращивания

1302

В чем разница между использованием оператора delete элемента массива в отличие от использования метод Array.splice?

Например:

myArray = ['a', 'b', 'c', 'd'];

delete myArray[1];
//  or
myArray.splice (1, 1);

Почему даже метод splice, если я могу удалить элементы массива, как я могу, с объектами?

  • 3
    Для .splice в циклах, посмотрите на этот вопрос: Удалить из массива в JavaScript .
  • 5
    @andynormancx Да, но этот ответ был опубликован буквально на следующий день и получил гораздо больше голосов - я бы сказал, что лучше написать, так и должно быть.
Показать ещё 2 комментария
Теги:
arrays
delete-operator
array-splice

24 ответа

1691
Лучший ответ

delete удалит свойство объекта, но не переиндексирует массив или не обновляет его длину. Это означает, что он выглядит как undefined:

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> delete myArray[0]
  true
> myArray[0]
  undefined

Обратите внимание, что на самом деле оно не установлено в значение undefined, скорее свойство удаляется из массива, что делает его undefined. Инструменты Chrome dev делают это различие прозрачным, печатая empty при регистрации массива.

> myArray[0]
  undefined
> myArray
  [empty, "b", "c", "d"]

myArray.splice(start, deleteCount) фактически удаляет элемент, переиндексирует массив и изменяет его длину.

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> myArray.splice(0, 2)
  ["a", "b"]
> myArray
  ["c", "d"]
  • 53
    исправление для строки 3: [undefined, 'b', 'c', 'd'] (это не строка 'undefined', а специальное значение undefined)
  • 0
    Почему склеивают, а не режут?
Показать ещё 9 комментариев
345

Метод Array.remove()

John Resig, создатель jQuery создал очень удобный метод Array.remove, который я всегда использую в своих проектах.

// 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);
};

и вот несколько примеров того, как это можно использовать:

// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);

Веб-сайт John

  • 4
    +1 Для Array.remove (). Однако не очень приятно, когда передаются строковые аргументы (в отличие от большинства методов Array, например [1,2,3].slice('1'); // =[2,3] ), поэтому безопаснее изменить его на var rest = this.slice(parseInt(to || from) + 1 || this.length);
  • 0
    Я обнаружил, что это вызывает асинхронную проблему. Потерялся ли поток перед this.push.apply ()?
Показать ещё 13 комментариев
95

Поскольку удаление только удаляет объект из элемента в массиве, длина массива не изменится. Splice удаляет объект и сокращает массив.

В следующем коде будут отображаться символы "a", "b", "undefined", "d"

myArray = ['a', 'b', 'c', 'd']; delete myArray[2];

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

В то время как это будет отображать "a", "b", "d"

myArray = ['a', 'b', 'c', 'd']; myArray.splice(2,1);

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}
  • 11
    Отличный пример, за исключением неоднозначности во втором примере с использованием 1,1 - первый 1 относится к индексу в массиве, чтобы начать соединение, второй 1 - это количество элементов, которые нужно удалить. Таким образом, чтобы удалить 'c' из исходного массива, используйте myArray.splice(2,1)
66

Я наткнулся на этот вопрос, пытаясь понять, как удалить каждое вхождение элемента из массива. Здесь сравнение splice и delete для удаления каждого 'c' из массива items.

var items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  items.splice(items.indexOf('c'), 1);
}

console.log(items); // ["a", "b", "d", "a", "b", "d"]

items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  delete items[items.indexOf('c')];
}

console.log(items); // ["a", "b", undefined, "d", "a", "b", undefined, "d"]
​
  • 0
    очень полезное руководство для меня. Заранее спасибо...
14

От Ссылка на Core JavaScript 1.5 > Операторы > Специальные операторы > delete Operator:

Когда вы удаляете элемент массива, длина массива не изменяется. Для Например, если вы удалите [3], [4] еще [4], а [3] - undefined. Эта сохраняется, даже если вы удалите последний элемент массива (удалить а [a.length-1]).

10

splice будет работать с числовыми индексами.

тогда как delete можно использовать против других типов индексов.

Пример:

delete myArray['text1'];
  • 9
    Когда вы говорите «любые другие виды индексов», вы больше не говорите о массивах, а скорее об объектах, о которых спрашивает ОП.
  • 2
    @YiJiang: массивы являются объектами. Indizes являются свойствами. Нет никакой разницы.
9

Возможно, стоит упомянуть, что сращивание работает только с массивами. (Свойства объекта нельзя полагаться на последовательный порядок.)

Чтобы удалить пару ключ-значение из объекта, удалить на самом деле то, что вы хотите:

delete myObj.propName;     // , or:
delete myObj["propName"];  // Equivalent.
  • 0
    delete не переупорядочивает ключи массива, поэтому: var arr = [1,2,3,4,5]; удалить обр [3]; for (var i = 0; i <= arr.length; i ++) console.log (arr [i]); будет демонстрировать неожиданные результаты.
  • 0
    Это правда. Поэтому, если вы не хотите оставить неопределенный элемент в этом месте, НЕ используйте delete для ключей массива! Первоначально я добавил этот комментарий, чтобы включить ссылку на правильное использование удаления.
Показать ещё 1 комментарий
8

Как указано много раз выше, использование splice() кажется идеальным сочетанием. Документация в Mozilla:

Метод splice() изменяет содержимое массива, удаляя существующие элементы и/или добавляя новые элементы.

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];

myFish.splice(2, 0, 'drum'); 
// myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"]

myFish.splice(2, 1); 
// myFish is ["angel", "clown", "mandarin", "sturgeon"]

Синтаксис

array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)

Параметры

начало

Индекс, с которого нужно начинать изменять массив. Если значение больше длины массива, фактический начальный индекс будет установлен на длину массива. Если отрицательный, начнется с того, что многие элементы с конца.

deleteCount

Целое число, указывающее количество старых элементов массива для удаления. Если deleteCount равно 0, элементы не удаляются. В этом случае вы должны указать хотя бы один новый элемент. Если deleteCount больше, чем количество элементов, оставшихся в массиве, начиная с начала, все элементы в конце массива будут удалены.

Если deleteCount опущен, deleteCount будет равен (arr.length - start).

item1, item2,...

Элементы для добавления в массив, начиная с начального индекса. Если вы не укажете какие-либо элементы, splice() будет удалять только элементы из массива.

Возвращаемое значение

Массив, содержащий удаленные элементы. Если удаляется только один элемент, возвращается массив из одного элемента. Если элементы не удалены, возвращается пустой массив.

[...]

  • 0
    @ downvoter: почему downvote? хочешь объяснить или нет?
7

удалить против сращивания

когда вы удаляете элемент из массива

var arr = [1,2,3,4]; delete arr[2]; //result [1, 2, 3:, 4]
console.log(arr)

когда ты склеиваешь

var arr = [1,2,3,4]; arr.splice(1,1); //result [1, 3, 4]
console.log(arr);

в случае удаления элемент удаляется, но индекс остается пустым

в то время как в случае сращивания элемент удаляется, а индекс остальных элементов соответственно уменьшается

7

delete действует как ситуация реального мира, он просто удаляет элемент, но длина массива остается неизменной:

пример из node терминала:

> var arr = ["a","b","c","d"];
> delete arr[2]
true
> arr
[ 'a', 'b', , 'd', 'e' ]

Вот функция, чтобы удалить элемент массива по индексу, используя slice(), он принимает значение arr как первый arg и индекс члена, который вы хотите удалить, как второй аргумент. Как вы можете видеть, он фактически удаляет член массива и уменьшает длину массива на 1

function(arr,arrIndex){
    return arr.slice(0,arrIndex).concat(arr.slice(arrIndex + 1));
}

То, что делает вышеприведенная функция, включает все члены до индекса и все члены после индекса и объединяет их вместе и возвращает результат.

Ниже приведен пример использования вышеприведенной функции как модуля node, так как терминал будет полезен:

> var arr = ["a","b","c","d"]
> arr
[ 'a', 'b', 'c', 'd' ]
> arr.length
4 
> var arrayRemoveIndex = require("./lib/array_remove_index");
> var newArray = arrayRemoveIndex(arr,arr.indexOf('c'))
> newArray
[ 'a', 'b', 'd' ] // c ya later
> newArray.length
3

обратите внимание, что это не будет работать с одним массивом с обманами в нем, потому что indexOf ( "c" ) просто получит первое появление и только сплайсирует и удаляет найденный первый "c".

5

Вы можете использовать что-то вроде этого

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

Если вы хотите итерации большого массива и выборочного удаления элементов, было бы дорого вызвать splice() для каждого удаления, потому что splice() должен будет повторно индексировать последующие элементы каждый раз. Поскольку массивы ассоциативны в Javascript, было бы более эффективно удалять отдельные элементы, а затем снова индексировать массив.

Вы можете сделать это, построив новый массив. например

function reindexArray( array )
{
       var result = [];
        for( var key in array )
                result.push( array[key] );
        return result;
};

Но я не думаю, что вы можете изменить значения ключей в исходном массиве, что было бы более эффективным - похоже, вам, возможно, придется создать новый массив.

Обратите внимание, что вам не нужно проверять записи "undefined", поскольку они фактически не существуют, и цикл for не возвращает их. Это артефакт печати массива, который отображает их как undefined. Они не существуют в памяти.

Было бы неплохо, если бы вы могли использовать что-то вроде slice(), которое было бы быстрее, но оно не индексируется повторно. Кто-нибудь знает лучший способ?


Собственно, вы, вероятно, можете сделать это на месте, что, вероятно, будет более эффективным, с точки зрения производительности:

reindexArray : function( array )
{
    var index = 0;                          // The index where the element should be
    for( var key in array )                 // Iterate the array
    {
        if( parseInt( key ) !== index )     // If the element is out of sequence
        {
            array[index] = array[key];      // Move it to the correct, earlier position in the array
            ++index;                        // Update the index
        }
    }

    array.splice( index );  // Remove any remaining elements (These will be duplicates of earlier items)
},
  • 0
    Я считаю индекс ++; должно произойти за пределами «если». Делать редактирование
2

В настоящее время существует два способа сделать это

  • используя splice()

    arrayObject.splice(index, 1);

  • используя delete

    delete arrayObject[index];

Но я всегда предлагаю использовать сплайсинг для объектов массива и удалить атрибуты объекта, потому что delete не обновляет длину массива.

2

Это разные вещи, которые имеют разные цели.

splice является специфичным для массива и при использовании для удаления удаляет записи из массива и перемещает все предыдущие записи до заполнения пробела. (Он также может использоваться для вставки записей или обоих одновременно.) splice изменит length массива (если это не вызов no-op: theArray.splice(x, 0)).

delete не зависит от массива; он предназначен для использования на объектах: он удаляет свойство (пару ключ/значение) из объекта, в котором вы его используете. Он применяется только к массивам, потому что стандартные (например, не типизированные) массивы в JavaScript вообще не являются массивами *, они являются объектами с особой обработкой для определенных свойств, таких как те, чьи имена являются "индексами массива" (которые определены как имена строк "​​... число которых значение i находится в диапазоне +0 ≤ i < 2^32-1" ) и length. Когда вы используете delete для удаления записи массива, все, что она делает, это удаление записи; он не перемещает другие записи, следуя за ним, чтобы заполнить пробел, и поэтому массив становится "разреженным" (имеет некоторые записи, отсутствующие полностью). Это не влияет на length.

Несколько текущих ответов на этот вопрос неправильно утверждают, что использование delete "устанавливает запись в undefined". Это не правильно. Он полностью удаляет запись (свойство), оставляя пробел.

Позвольте использовать некоторый код, чтобы проиллюстрировать различия:

console.log("Using `splice`:");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a.splice(0, 1);
console.log(a.length);            // 4
console.log(a[0]);                // "b"

console.log("Using `delete`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
delete a[0];
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // false
console.log(a.hasOwnProperty(0)); // false

console.log("Setting to `undefined`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a[0] = undefined;
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // true
console.log(a.hasOwnProperty(0)); // true

* (это сообщение в моем анемичном маленьком блоге)

2
function remove_array_value(array, value) {
    var index = array.indexOf(value);
    if (index >= 0) {
        array.splice(index, 1);
        reindex_array(array);
    }
}
function reindex_array(array) {
   var result = [];
    for (var key in array) {
        result.push(array[key]);
    }
    return result;
}

Пример:

var example_arr = ['apple', 'banana', 'lemon'];   // length = 3
remove_array_value(example_arr, 'banana');

банана удаляется, а длина массива = 2

2

Почему бы просто не фильтровать? Я думаю, что это самый ясный способ рассмотреть массивы в js.

myArray = myArray.filter(function(item){
    return item.anProperty != whoShouldBeDeleted
});
  • 0
    Как насчет массива с сотнями (если не тысячами) записей, из которых нужно удалить только 3 из них?
  • 0
    хорошая точка зрения. Я использую этот метод для разреженных массивов, длина которых не превышает 200 или 300 и работает очень хорошо. Тем не менее, я думаю, что библиотеки, такие как подчеркивание, должны быть предпочтительнее, если вам нужно управлять такими большими массивами.
Показать ещё 1 комментарий
1

Разницу можно увидеть, зарегистрировав длину каждого массива после применения оператора delete и метода splice(). Например:

оператор удаления

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];

console.log(trees); // ["redwood", "bay", "cedar", empty, "maple"]
console.log(trees.length); // 5

Оператор delete удаляет элемент из массива, но "заполнитель" элемента все еще существует. Поскольку delete не удаляет элемент полностью, длина массива остается той же самой, которая по-прежнему равна 5.

метод splice()

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);

console.log(trees); // ["redwood", "bay", "cedar", "maple"]
console.log(trees.length); // 4

Метод splice() удаляет не только целевое значение, но и "заполнитель". Это отражает длину массива 4.

1

ОК, представьте, что у нас есть этот массив ниже:

const arr = [1, 2, 3, 4, 5];

Позвольте сначала удалить:

delete arr[1];

и это результат:

[1, empty, 3, 4, 5];

пусто!, и пусть оно получится:

arr[1]; //undefined

Значит, просто удалено значение и теперь undefined, так что длина будет одинаковой, и она вернет true...

Пусть reset наш массив и сделает это с помощью сращивания на этот раз:

arr.splice(1, 1);

и на этот раз это результат:

[1, 3, 4, 5];

Как вы видите, длина массива изменилась и arr[1] теперь 3...

Также это вернет удаленный элемент в массиве, который в этом случае [3]...

0

delete: delete удалит свойство объекта, но не переиндексирует массив или не обновляет его длину. Это заставляет его выглядеть так, как будто он не определен:

splice: фактически удаляет элемент, переиндексирует массив и изменяет его длину.

Удалить элемент из последнего

arrName.pop();

Удалить элемент с первого

arrName.shift();

Удалить из середины

arrName.splice(starting index,number of element you wnt to delete);

Ex: arrName.splice(1,1);

Удалить один элемент из последнего

arrName.splice(-1);

Удалить с помощью номера индекса массива

 delete arrName[1];
0

Для тех, кто хочет использовать Lodash, можно использовать: myArray = _.without(myArray, itemToRemove)

Или как я использую в Angular2

import { without } from 'lodash';
...
myArray = without(myArray, itemToRemove);
...
0

Если нужный элемент находится посередине (скажем, мы хотим удалить 'c', индекс которого равен 1), вы можете использовать:

var arr = ['a','b','c'];
var indexToDelete = 1;
var newArray = arr.slice(0,indexToDelete).combine(arr.slice(indexToDelete+1, arr.length))
0

Самый простой способ - это, вероятно,

var myArray = ['a', 'b', 'c', 'd'];
delete myArray[1]; // ['a', undefined, 'c', 'd']. Then use lodash compact method to remove false, null, 0, "", undefined and NaN
myArray = _.compact(myArray); ['a', 'c', 'd'];

Надеюсь, это поможет. Ссылка: https://lodash.com/docs#compact

  • 1
    Если кто-то наткнется на это, интересно о compact ... нет необходимости в Lodash. Попробуйте myArray.filter(function(n){return n;})
0

IndexOf принимает также ссылочный тип. Предположим следующий сценарий:

var arr = [{item: 1}, {item: 2}, {item: 3}];
var found = find(2, 3); //pseudo code: will return [{item: 2}, {item:3}]
var l = found.length;

while(l--) {
   var index = arr.indexOf(found[l])
      arr.splice(index, 1);
   }
   
console.log(arr.length); //1

По-другому:

var item2 = findUnique(2); //will return {item: 2}
var l = arr.length;
var found = false;
  while(!found && l--) {
  found = arr[l] === item2;
}

console.log(l, arr[l]);// l is index, arr[l] is the item you look for
-1
function deleteFromArray(array, indexToDelete){
  var remain = new Array();
  for(var i in array){
    if(array[i] == indexToDelete){
      continue;
    }
    remain.push(array[i]);
  }
  return remain;
}

myArray = ['a', 'b', 'c', 'd'];
deleteFromArray(myArray , 0);

//result: myArray = ['b', 'c', 'd'];

  • 8
    Это неправильно во многих отношениях.
  • 0
    @ChrisDennis почему? (без сарказма или злого умысла, это искренний вопрос)
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню