429

I have an array of objects like so:

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

How do I remove a specific one based on its property?

e.g. How would I remove the array object with 'money' as the field property?

imperium2335
  • 23,402
  • 38
  • 111
  • 190

12 Answers12

587

One possibility:

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

Please note that filter creates a new array. Any other variables referring to the original array would not get the filtered data although you update your original variable myArray with the new reference. Use with caution.

Charlie
  • 22,886
  • 11
  • 59
  • 90
jAndy
  • 231,737
  • 57
  • 305
  • 359
  • 7
    Note that `filter()` is only available for Internet Explorer 9+ – jessegavin Apr 29 '13 at 14:51
  • @jessegavin indeed. I should have mentioned that there are plenty of good *es5 shim* libraries available, which mimic the functionality (just in case you want to support legacy browsers) – jAndy Apr 29 '13 at 14:57
  • 8
    `filter()` creates a new array, which is fine if you're able to reassign the variable and know that there aren't other areas of code that have references to it. This won't work if you specifically need to modify the original array object. – Brian Glick Sep 26 '14 at 17:55
  • 2
    What if the array is a tree structure ar beforeDeleteOperationArray=[ { "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] } ] and I want to delete id:23 – forgottofly Jan 18 '17 at 11:37
  • @forgottofly good point - answer works only for limited cases. Did you found answer to your question? – JackTheKnife Jul 19 '18 at 20:16
  • No @JackTheKnife – forgottofly Jul 23 '18 at 06:56
  • The Mozilla doc is pretty clear on it. `filter` is the best option you have : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/filter You can check support at the bottom of the page. It is all green for *Chrome*, *FireFox*, *Edge*, *IE9+*, *Opera*, *Safari*. On mobile, all major browsers support it. You are not in 2010, please keep code clean and stick to browsers standards. – gabrielstuff Sep 01 '20 at 20:19
  • Since the filter method will loop through the array, is it safe to assume that this will work fine with thousands of entries? My particular case is that I store websockets connections (each client has at least one, making them quite a lot) in an array on my server and upon disconnection need to remove the entry. – undefined Aug 16 '21 at 01:24
109

Iterate through the array, and splice out the ones you don't want. For easier use, iterate backwards so you don't have to take into account the live nature of the array:

for (var i = myArray.length - 1; i >= 0; --i) {
    if (myArray[i].field == "money") {
        myArray.splice(i,1);
    }
}
user1438038
  • 5,821
  • 6
  • 60
  • 94
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 3
    what do you mean by the live nature of the array ? @Neit the Dark Absol – sisimh Jun 01 '15 at 12:46
  • 45
    @sisimh he means that if you iterate forwards over an array by using its length as part of the iteration logic and its length changes because it has elements removed or added you can end up running off the end of the array or not doing the operation for every item in the array. Going backwards makes that much less likely as it works towards a static 0 index rather than a moving length. – Klors Jul 10 '15 at 16:14
  • 2
    What if the array is a tree structure ar beforeDeleteOperationArray=[ { "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] } ] and I want to delete id:23 – forgottofly Jan 18 '17 at 11:37
  • Kinda obvious but if you are only expecting to remove a single unique element, you can throw a break into the 'if' statement for performance so the loop doesn't needlessly iterate over the rest of the array. – Patrick Borkowicz Mar 31 '17 at 13:21
  • @Klors Thanks for explaining. Is it good to always read the array backwards as in the answer? – kittu Jul 17 '17 at 08:47
  • @Satyadev It's required here because `splice` changes the array. – Niet the Dark Absol Jul 17 '17 at 09:07
  • @Satyadev If iterating backwards is what you need, then go ahead and do it. If not, don't bother. – Niet the Dark Absol Jul 17 '17 at 09:15
  • @NiettheDarkAbsol Actually reading array in backwards is faster. Just figured it out from this link: https://stackoverflow.com/questions/8689573/why-is-iterating-through-an-array-backwards-faster-then-forwards?lq=1 – kittu Jul 17 '17 at 09:18
  • @Satyadev Read the accepted answer on that question. – Niet the Dark Absol Jul 17 '17 at 09:19
  • If myarray has length of 1 this loop will immediately end. Also when the if condition is met it's usually advised to instantly stop the remaining iteration. – ShadowGames Dec 05 '22 at 02:32
102

Say you want to remove the second object by its field property.

With ES6 it's as easy as this.

myArray.splice(myArray.findIndex(item => item.field === "cStatus"), 1)
Ry-
  • 218,210
  • 55
  • 464
  • 476
Peracek
  • 1,801
  • 1
  • 15
  • 17
  • 8
    I tried this but instead of "removing" 3rd item from OP's array, your code "filtered" and displayed the 3rd item only. – Compaq LE2202x Jul 30 '18 at 12:52
  • 13
    @CompaqLE2202x 2 years later it's probably already obvious to you, but for future developers: `splice` changes the original array, so the value you get back is the item that was removed, but if you next look at `myArray` the item will be missing. – David Mulder Apr 24 '20 at 14:20
  • 8
    If the element is not found by findIndex, -1 is returned and the last element is removed by splice although it doesn't match the predicate. – Yannic Sep 29 '20 at 16:10
64

In ES6, just one line.

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

:)

Supun Kavinda
  • 1,355
  • 14
  • 13
26

You can use lodash's findIndex to get the index of the specific element and then splice using it.

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

Update

You can also use ES6's findIndex()

The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise -1 is returned.

const itemToRemoveIndex = myArray.findIndex(function(item) {
  return item.field === 'money';
});

// proceed to remove an item only if it exists.
if(itemToRemoveIndex !== -1){
  myArray.splice(itemToRemoveIndex, 1);
}
Sridhar
  • 11,466
  • 5
  • 39
  • 43
  • What is the array is a tree structure? – forgottofly Jan 18 '17 at 11:34
  • @forgottofly tree structure? I think `myArray` here is an array of objects. – Sridhar Jan 18 '17 at 12:17
  • 4
    What if the array is a tree structure var beforeDeleteOperationArray=[ { "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] } ] and I want to delete id:23 – forgottofly Jan 18 '17 at 13:59
  • 2
    If the element is not found by findIndex (ES6 version), -1 is returned and the last element is removed by splice although it doesn't match the predicate. – Yannic Sep 29 '20 at 16:08
  • 1
    @Yannic Nice catch. Thanks for pointing it out. Updated my answer for it. – Sridhar Oct 07 '20 at 06:57
  • Could probably also use ternary for that to keep it as a single line and avoid additional variable creation – undefined Aug 16 '21 at 01:34
16

We can remove the element based on the property using the below 2 approaches.

  1. Using filter method
testArray.filter(prop => prop.key !== 'Test Value')
  1. Using splice method. For this method we need to find the index of the propery.
const index = testArray.findIndex(prop => prop.key === 'Test Value')
testArray.splice(index,1)
Senthuran
  • 1,583
  • 2
  • 15
  • 19
  • the array filter() function does not modify the original array, therefore, your code needs a let newArray = testArray.filter(prop => prop.key !== 'Test Value'). – Peter Utekal Dec 04 '22 at 21:36
9

Here's another option using jQuery grep. Pass true as the third parameter to ensure grep removes items that match your function.

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

If you're already using jQuery then no shim is required, which is could be useful as opposed to using Array.filter.

sifriday
  • 4,342
  • 1
  • 13
  • 24
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

Element is an object in the array. 3rd parameter true means will return an array of elements which fails your function logic, false means will return an array of elements which fails your function logic.

Sandeep sandy
  • 387
  • 7
  • 14
2

Using the lodash library:

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>
Greg Pettit
  • 10,749
  • 5
  • 53
  • 72
Parth Raval
  • 4,097
  • 3
  • 23
  • 36
2

Based on some comments above below is the code how to remove an object based on a key name and key value

 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,795
  • 8
  • 57
  • 117
1

jAndy's solution is probably best, but if you can't rely on filter you could do something like:

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;
}
Rob M.
  • 35,491
  • 6
  • 51
  • 50
1

Following is the code if you are not using jQuery. Demo

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

You can also use underscore library which have lots of function.

Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support

Umair Saleem
  • 1,055
  • 5
  • 19
  • 7
    This is a very dangerous example to leave on the web... it works with the example data, but not with anything else. splice(i) means that it will remove all elements in the array starting at and after the first instance where value is money, which down not satisfy the requirement from op at all. If we changed to splice(i,1) it would still be incorrect because it would not evaluate the next sequential item (you would have to decrement i as well) This is why you should process remove operations in arrays backwards, so that removing an item doesn't alter the indexes of the next items to process – Chris Schaller Aug 01 '16 at 00:46