Удалить элемент массива на основе свойства объекта

271

У меня есть массив объектов, таких как:

var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];

Как мне удалить конкретный на основе его свойства?

Например, как бы я удалил объект массива с 'money' в качестве свойства поля?

imperium2335
источник

Ответы:

384

Одна возможность:

myArray = myArray.filter(function( obj ) {
    return obj.field !== 'money';
});

Обратите внимание, что filterсоздает новый массив. Любые другие переменные, ссылающиеся на исходный массив, не получат отфильтрованные данные, хотя вы обновите исходную переменную myArrayновой ссылкой. Используйте с осторожностью.

JANDY
источник
6
Обратите внимание, что filter()доступно только для Internet Explorer 9+
jessegavin
@ jessegavin действительно. Я должен отметить , что есть много хорошего ES5 прокладка библиотеки доступны, которые имитируют функциональность (только в случае , если вы хотите , чтобы поддержка устаревших браузеров)
JANDY
3
filter()создает новый массив, что хорошо, если вы можете переназначить переменную и знать, что нет других областей кода, которые имеют ссылки на нее. Это не сработает, если вам нужно изменить исходный объект массива.
Брайан Глик
2
Что если массив является древовидной структурой ar beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, { "ID": 23, "имя": "измененный тест 23"}]}] и я хочу , чтобы удалить ID: 23
forgottofly
@ забыл хороший момент - ответ работает только в ограниченных случаях. Вы нашли ответ на свой вопрос?
JackTheKnife
88

Итерируйте по массиву и spliceвыводите те, которые вам не нужны. Для более легкого использования итерируйте в обратном направлении, чтобы вам не приходилось учитывать динамический характер массива:

for (var i = myArray.length - 1; i >= 0; --i) {
    if (myArray[i].field == "money") {
        myArray.splice(i,1);
    }
}
Нит Тёмный Абсол
источник
3
что вы подразумеваете под живой природой массива? @Neit Темный Absol
sisimh
29
@sisimh он имеет в виду, что если вы выполняете итерацию вперед по массиву, используя его длину как часть логики итерации и изменяя его длину, поскольку в нем удалены или добавлены элементы, вы можете в конечном итоге запустить конец массива или не выполнять операцию для каждый элемент в массиве. Движение назад делает это гораздо менее вероятным, так как оно работает в направлении статического индекса 0, а не скользящей длины.
Klors
2
Что если массив является древовидной структурой ar beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, { "ID": 23, "имя": "измененный тест 23"}]}] и я хочу , чтобы удалить ID: 23
forgottofly
Вроде бы очевидно, но если вы ожидаете удалить только один уникальный элемент, вы можете бросить разрыв в оператор if для повышения производительности, чтобы цикл не занимал ненужную итерацию по всему массиву.
Патрик
@Klors Спасибо за объяснение. Хорошо ли всегда читать массив задом наперед, как в ответе?
Китту
38

Скажем, вы хотите удалить второй объект по его свойству поля.

С ES6 это так просто.

myArray.splice(myArray.findIndex(item => item.field === "cStatus"), 1)
Peracek
источник
7
Я попробовал это, но вместо того, чтобы "удалить" 3-й элемент из массива OP, ваш код "отфильтровывался" и отображал только 3-й элемент.
Compaq LE2202x
1
@ CompaqLE2202x 2 года спустя это, вероятно, уже очевидно для вас, но для будущих разработчиков: spliceизменяет исходный массив, поэтому возвращаемое значение - это элемент, который был удален, но если вы в следующий раз посмотрите на myArrayэлемент, он будет отсутствовать.
Дэвид Малдер
17

Вы можете использовать findIndex lodash, чтобы получить индекс конкретного элемента, а затем соединить его.

myArray.splice(_.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);

Обновить

Вы также можете использовать find6dex () ES6

Метод findIndex () возвращает индекс первого элемента в массиве, который удовлетворяет предоставленной функции тестирования. В противном случае -1 возвращается.

myArray.splice(myArray.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);
Шридхар
источник
Какой массив представляет собой древовидную структуру?
forgottofly
@ забыли древовидную структуру? Я думаю, что myArrayздесь массив объектов.
Шридхар
4
Что если массив представляет собой древовидную структуру var beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, { "ID": 23, "имя": "измененный тест 23"}]}] и я хочу , чтобы удалить ID: 23
forgottofly
9

Вот еще один вариант, используя jQuery grep. Передайте trueв качестве третьего параметра, чтобы grep удалял элементы, которые соответствуют вашей функции.

users = $.grep(users, function(el, idx) {return el.field == "money"}, true)

Если вы уже используете jQuery, тогда никакая подкладка не требуется, что может быть полезно в отличие от использования Array.filter.

sifriday
источник
8

В ES6 всего одна строчка.

const arr = arr.filter(item => item.key !== "some value");

:)

Супун Кавинда
источник
3

Ниже приведен код, если вы не используете jQuery. демонстрация

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];

alert(myArray.length);

for(var i=0 ; i<myArray.length; i++)
{
    if(myArray[i].value=='money')
        myArray.splice(i);
}

alert(myArray.length);

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

Underscore - это библиотека утилитарных поясов для JavaScript, которая обеспечивает большую поддержку функционального программирования.

Умайр Салим
источник
5
Это очень опасный пример, чтобы оставить его в Интернете ... он работает с данными примера, но не с чем-либо еще. splice (i) означает, что он удалит все элементы в массиве, начиная с и после первого экземпляра, где value - это деньги, которые вообще не удовлетворяют требованию op. Если бы мы изменили на splice (i, 1), он все равно был бы неправильным, потому что он не оценивал бы следующий последовательный элемент (вам также пришлось бы уменьшить i). Вот почему вы должны обрабатывать операции удаления в массивах в обратном направлении, так что удаление элемент не изменяет индексы следующих элементов для обработки
Крис Шаллер
3
var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];
console.log(myArray.length); //3
myArray = $.grep(myArray, function(element, index){return element.field == "money"}, true);
console.log(myArray.length); //2

Элемент - это объект в массиве. 3-й параметр trueозначает, что вернет массив элементов, который не соответствует логике вашей функции, falseозначает, что вернет массив элементов, который не соответствует логике вашей функции.

Сандип песчаный
источник
3

На основе приведенных выше комментариев приведен код удаления объекта на основе имени и значения ключа.

 var items = [ 
  { "id": 3.1, "name": "test 3.1"}, 
  { "id": 22, "name": "test 3.1" }, 
  { "id": 23, "name": "changed test 23" } 
  ]

    function removeByKey(array, params){
      array.some(function(item, index) {
        return (array[index][params.key] === params.value) ? !!(array.splice(index, 1)) : false;
      });
      return array;
    }

    var removed = removeByKey(items, {
      key: 'id',
      value: 23
    });

    console.log(removed);
JackTheKnife
источник
3

Использование библиотеки lodash :

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];
var newArray = _.remove(myArray, function(n) {
  return n.value === 'money';;
});
console.log('Array');
console.log(myArray);
console.log('New Array');
console.log(newArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

Парт Равал
источник
1

Решение jAndy, вероятно, лучше, но если вы не можете полагаться на фильтр, вы можете сделать что-то вроде:

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: "money"}
];

myArray.remove_key = function(key){
    var i = 0, 
        keyval = null;
    for( ; i < this.length; i++){
        if(this[i].field == key){
            keyval = this.splice(i, 1);
            break;
        }
    }
    return keyval;
}
Роб М.
источник
1
Почему я не могу положиться на фильтр ()?
imperium2335,
2
Потому что это часть JavaScript 1.6, которая не поддерживается IE8 и ниже или более старых браузеров.
Роб М.
-1

Используя библиотеку lodash, все просто

_.remove(myArray , { field: 'money' });
Gimnath
источник