143

Say I have this code

var arr = [{id:1,name:'a'},{id:2,name:'b'},{id:3,name:'c'}];

and I want to remove the item with id = 3 from the array. Is there a way of doing this without splicing? Maye something using underscore or something like that?

Thanks!

Tarik
  • 79,711
  • 83
  • 236
  • 349
climboid
  • 6,932
  • 14
  • 44
  • 71
  • If you don't want to create a new array, splicing is the only choice. I bet underscore uses it too (internally, if such a method exist). – Felix Kling Jun 07 '13 at 23:10
  • 6
    What's wrong with splicing? – Šime Vidas Jun 07 '13 at 23:11
  • Have you checked underscore's reference? – Šime Vidas Jun 07 '13 at 23:12
  • Just using plain JavaScript, this is a duplicate of [remove objects from array by object property](http://stackoverflow.com/q/16491758/218196). – Felix Kling Jun 07 '13 at 23:13
  • 5
    well is not duplicate as it has the tag for underscore.js – Garis M Suero Oct 29 '13 at 17:39
  • Unfortunately, I can't answer this question yet, but you can use _.reject(collection, predicate, [context])(http://underscorejs.org/#reject) for this case. This method is opposite of filter, so it returns the values in list without the elements that the truth test (predicate) passes. This is exactly what you need ;) – Jake Blues Jul 29 '14 at 10:29
  • why not `arr = arr.filter(v => v.id != 3);`? Never understand, why peoples use some kind of frameworks to do common action in javascript, using it's native api? You are afraid that your array will be `null` or `not array`? Or you trust to library more than native api, that already used inside of this library? – degr Jan 17 '17 at 07:08

12 Answers12

288

Just using plain JavaScript, this has been answered already: remove objects from array by object property.

Using underscore.js, you could combine .findWhere with .without:

var arr = [{
  id: 1,
  name: 'a'
}, {
  id: 2,
  name: 'b'
}, {
  id: 3,
  name: 'c'
}];

//substract third
arr = _.without(arr, _.findWhere(arr, {
  id: 3
}));
console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Although, since you are creating a new array in this case anyway, you could simply use _.filter or the native Array.prototype.filter function (just like shown in the other question). Then you would only iterate over array once instead of potentially twice like here.

If you want to modify the array in-place, you have to use .splice. This is also shown in the other question and undescore doesn't seem to provide any useful function for that.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    Yep this works perfectly, I did go over the underscore documentation but didn't quite understand how to pull it out with without. Thank you! – climboid Jun 07 '13 at 23:22
  • 10
    Wouldn't _.reject or _.filter() be a lot more efficient here? You'd end up with two iterations of the list just to pull out one item. – Rick Strahl Sep 23 '13 at 01:12
  • 1
    This might be a duplicate but this is the better answer. – Michael J. Calkins Nov 21 '13 at 18:44
  • Underscore does not provide `.splice` functionality because splice is a destructive function. For further explanation, see [my answer here](http://stackoverflow.com/a/18363134/2479481). – Luke Willis Apr 23 '15 at 16:00
  • 2
    @RickStrahl You are right. `_.reject` looks like a better selection here. – Tarik Apr 29 '15 at 14:44
  • If ever someone want to pop last element, just simply: `_.without(arr, _.last(arr))` and for first element just use `_.first` – lukaserat Oct 21 '16 at 09:04
  • 1
    @lukaserat to pop the last element, use [`arr.pop()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop?v=control)... – Emile Bergeron Jun 20 '17 at 14:01
100

You can use Underscore .filter

    var arr = [{
      id: 1,
      name: 'a'
    }, {
      id: 2,
      name: 'b'
    }, {
      id: 3,
      name: 'c'
    }];

    var filtered = _(arr).filter(function(item) {
         return item.id !== 3
    });

Can also be written as:

var filtered = arr.filter(function(item) {
    return item.id !== 3
});

var filtered = _.filter(arr, function(item) {
    return item.id !== 3
});

Check Fiddle

You can also use .reject

Doug E Fresh
  • 820
  • 8
  • 22
Sushanth --
  • 55,259
  • 9
  • 66
  • 105
39

Use Underscore _.reject():

arr = _.reject(arr, function(d){ return d.id === 3; });
greenafrican
  • 2,516
  • 5
  • 27
  • 38
18

Underscore has a _without() method perfect for removing an item from an array, especially if you have the object to remove.

Returns a copy of the array with all instances of the values removed.

_.without(["bob", "sam", "fred"], "sam");

=> ["bob", "fred"]

Works with more complex objects too.

var bob = { Name: "Bob", Age: 35 };
var sam = { Name: "Sam", Age: 19 };
var fred = { Name: "Fred", Age: 50 };

var people = [bob, sam, fred]

_.without(people, sam);

=> [{ Name: "Bob", Age: 35 }, { Name: "Fred", Age: 50 }];

If you don't have the item to remove, just a property of it, you can use _.findWhere and then _.without.

PeteGO
  • 5,597
  • 3
  • 39
  • 70
  • 2
    Note: this only works because you're passing the sam object to without. If you instead pass `{ Name: "Sam", Age: 19 }` to without, rather than the variable sam, it no longer works. [Fiddle](https://jsfiddle.net/mx8k13vd/) – Adam Jun 01 '17 at 17:00
6

Please exercise care if you are filtering strings and looking for case insensitive filters. _.without() is case sensitive. You can also use _.reject() as shown below.

var arr = ["test","test1","test2"];

var filtered = _.filter(arr, function(arrItem) {
    return arrItem.toLowerCase() !== "TEST".toLowerCase();
});
console.log(filtered);
// ["test1", "test2"]

var filtered1 = _.without(arr,"TEST");
console.log(filtered1);
// ["test", "test1", "test2"]

var filtered2 = _.reject(arr, function(arrItem){ 
    return arrItem.toLowerCase() === "TEST".toLowerCase();
});
console.log(filtered2);
// ["test1", "test2"]
6

Other answers create a new copy of the array, if you want to modify the array in place you can use:

arr.splice(_.findIndex(arr, { id: 3 }), 1);

But that assumes that the element will always be found inside the array (because if is not found it will still remove the last element). To be safe you can use:

var index = _.findIndex(arr, { id: 3 });
if (index > -1) {
    arr.splice(index, 1);
}
Mariano Desanze
  • 7,847
  • 7
  • 46
  • 67
Sajjad Shirazi
  • 2,657
  • 26
  • 24
2

or another handy way:

_.omit(arr, _.findWhere(arr, {id: 3}));

my 2 cents

Nadeem
  • 419
  • 4
  • 13
  • 1
    omit works on `object` and returns an `object`. hence not vey good for working with `Arrays` where we might expect to get an `array` back after removing an element. – ScrapCode Jun 08 '16 at 09:06
  • 1
    So, *_.without* is the on you're looking at: ```_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); => [2, 3, 4]``` – Nadeem Jun 09 '16 at 17:44
2

Use can use plain JavaScript's Array#filter method like this:

var arr = [{id:1,name:'a'},{id:2,name:'b'},{id:3,name:'c'}];

var filteredArr = arr.filter(obj => obj.id != 3);

console.log(filteredArr);

Or, use Array#reduce and Array#concat methods like this:

var arr = [{id:1,name:'a'},{id:2,name:'b'},{id:3,name:'c'}];

var reducedArr = arr.reduce((accumulator, currObj) => {
  return (currObj.id != 3) ? accumulator.concat(currObj) : accumulator;
}, []);

console.log(reducedArr);

NOTE:

  • Both of these are pure functional approach (i.e. they don't modify the existing array).
  • No, external library is required in these approach (Vanilla JavaScript is enough).
BlackBeard
  • 10,246
  • 7
  • 52
  • 62
0

I used to try this method

_.filter(data, function(d) { return d.name != 'a' });

There might be better methods too like the above solutions provided by users

Bastin Robin
  • 907
  • 16
  • 30
0

By Using underscore.js

var arr = [{id:1,name:'a'},{id:2,name:'b'},{id:3,name:'c'}];

var resultArr = _.reject(arr,{id:3});

console.log(resultArr);

The result will be :: [{id:1name:'a'},{id:2,name:'c'}]

Viira
  • 3,805
  • 3
  • 16
  • 39
-1

You can use reject method of Underscore, below will return a new array which won't have array with particular match

arr = _.reject(arr, function(objArr){ return objArr.id == 3; });
STEEL
  • 8,955
  • 9
  • 67
  • 89
-1

lodash can be used:

_.compact(arr);
Christian
  • 4,902
  • 4
  • 24
  • 42
Saad Ahmed
  • 700
  • 1
  • 8
  • 15
  • Underscore has [compact](https://underscorejs.org/#compact), too. More importantly, this does not answer the question because _.compact only removes falsy values. – Julian Jun 11 '22 at 15:25