Видаліть елемент масиву на основі властивості об'єкта


270

У мене є масив таких об’єктів:

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

Як видалити конкретний на основі його властивості?

наприклад, як я можу видалити об'єкт масиву із властивістю поля "гроші"?

Відповіді:


382

Одна можливість:

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

Зверніть увагу, що filterстворюється новий масив. Будь-які інші змінні, що посилаються на вихідний масив, не отримають відфільтровані дані, хоча ви оновлюєте оригінальну змінну myArrayновою посиланням. Використовуйте обережно.


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, "name": "змінили тест 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 The Dark
Absol

29
@sisimh він означає, що якщо ви повторюєте вперед через масив, використовуючи його довжину як частину логіки ітерації, а її довжина змінюється, оскільки в ній є елементи, вилучені або додані, ви можете в кінцевому рахунку бігти з кінця масиву або не робити операції для кожен елемент у масиві. Повернення назад робить це набагато менш ймовірним, оскільки він працює в напрямку статичного 0 індексу, а не рухається довжини.
Клорс

2
Що робити, якщо масив - це структура дерева ar beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "activityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "змінили тест 23"}]}], і я хочу видалити id: 23
забувфліф

Якесь очевидне, але якщо ви тільки розраховуєте видалити єдиний унікальний елемент, ви можете кинути перерву в операторі "if" для продуктивності, щоб цикл не зайвий ітерація над рештою масиву.
Патрік Боркович

@Klors Дякую за пояснення. Чи добре завжди читати масив назад, як у відповіді?
kittu

37

Скажіть, що ви хочете видалити другий об’єкт за його властивістю поля.

З ES6 це так просто, як це.

myArray.splice(myArray.findIndex(item => item.field === "cStatus"), 1)

6
Я спробував це, але замість того, щоб "видалити" 3-й елемент з масиву ОП, ваш код "відфільтрував" і відображав лише 3-й елемент.
Compaq LE2202x

1
@ CompaqLE2202x через 2 роки, це, мабуть, вже очевидно для вас, але для майбутніх розробників: spliceзмінює початковий масив, тому значення, яке ви отримаєте назад, - це елемент, який було видалено, але якщо ви наступного погляду на myArrayелемент, він буде відсутній.
Девід Малдер

16

Ви можете використовувати lodI's findIndex, щоб отримати індекс конкретного елемента, а потім сплайсировать його.

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

Оновлення

Ви також можете використовувати findIndex () ES6 ()

Метод findIndex () повертає індекс першого елемента в масиві, який задовольняє наданій функції тестування. Інакше -1 повертається.

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

Що таке масив - це структура дерева?
забутофточка

@forgottofly структура дерева? Я думаю, myArrayтут є масив об’єктів.
Шрідхар

3
Що робити, якщо масив - це структура дерева var beforeDeleteOperationArray = [{"id": 3.1, "name": "test 3.1", "ActivityDetails": [{"id": 22, "name": "test 3.1"}, {"id": 23, "name": "змінили тест 23"}]}], і я хочу видалити id: 23
забувфліф

9

Ось ще один варіант використання jQuery grep. Передайте trueяк третій параметр, щоб гарантувати, що греп видаляє елементи, які відповідають вашій функції.

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

Якщо ви вже використовуєте jQuery, тоді не потрібно тримати щось, що може бути корисним на відміну від використання Array.filter.



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) означає, що він видалить усі елементи з масиву, починаючи з першого і після першого екземпляра, де значенням є гроші, які вниз зовсім не задовольняють вимогу від op. Якщо ми змінили на сплайс (i, 1), він все одно був би невірним, оскільки він не буде оцінювати наступний послідовний елемент (ви також повинні будете декрементувати i). Ось чому ви повинні обробити операції з видалення масивів назад, щоб видалити елемент не змінює індекси наступних оброблюваних елементів
Chris Schaller

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

Елемент - це об'єкт у масиві. Третій параметр trueозначає, що поверне масив елементів, який не відповідає вашій логіці функції, а falseзначить поверне масив елементів, який не відповідає вашій логіці функції.


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>


2

На підставі наведених нижче коментарів нижче - код, як видалити об’єкт на основі імені ключа та значення ключа

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

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
Чому я не зможу покластися на filter ()?
imperium2335

2
Тому що він є частиною JavaScript 1.6, який не підтримується IE8 та нижче чи старими браузерами.
Роб М.

-1

Використовувати бібліотеку lodash - це просто так

_.remove(myArray , { field: 'money' });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.