underscore
underscore copied to clipboard
Feature request: _.deleteWhere
Currently having array of objects, to delete one of them I need to write:
var collection = [{id: 1}, {id: 3}];
var objectToRemove = _.findWhere(collection, function (obj) { return obj.id === 3 });
var objectIndex = collection.indexOf(objectToRemove);
collection.splice(objectIndex, 1);
It would be nice to have in underscore something like:
_.deleteWhere(collection, {id: 2})
If you find this useful I can try to implement it and send a PR.
One of Underscore's philosophies is to expose reusable, composable methods so you can implement these types of special functions yourself, keeping the library small and purposefully managed. It should be fairly easy to do in your own copy with mixin
.
_.mixin({
deleteWhere: function(collection, predicate) {
var obj = _.findWhere(collection, predicate);
collection.splice(_.indexOf(collection, obj), 1);
}
});
_.deleteWhere(collection, {id: 2});
@akre54 It gets a bit trickier when you want to remove all matches and isn't something devs can compose easily.
@morgoth You can find this method in Lo-Dash as _.remove, (_.remove(array, {id: 2})
, or as an individual method npm package. I'm sure there's others on npm too.
If you go the _.mixin
route, implementing it on your own, you can leverage Underscore's new _.iteratee method to support callbacks as well as "_.pluck" & "_where" callback shorthands.
@joshuacc Have y'all considered array/object mutator methods for underscore-contrib? It's one of those things that seems to come up from time to time.
Related to #1848.
@jdalton Not so far, but it sounds reasonable to me. This example in particular seems quite useful. I'll create an issue to track it.
I think this would be a nice function to add to Underscore...
Usefulness or niceness aside, it fits closer to a mixin or underscore.contrib than a core underscore method.
The problem is, ideally we'd also include a more generic .delete that takes an array and a reference to an object, but that's not much more than sugar over arr.splice(.indexOf(arr, obj), 1)). It could be composed with findWhere, but I'm not sure the extra abstraction (and the addition to the Underscore API) is worth it.
On Fri, Sep 19, 2014 at 4:52 PM, Graeme Yeates [email protected] wrote:
It's not a functional method but other libs like Mootools http://mootools.net/docs/core/Types/Array#Array:erase have this as well
I'd [image: :+1:] this addition
— Reply to this email directly or view it on GitHub https://github.com/jashkenas/underscore/issues/1856#issuecomment-56233853 .
I think of it more like a friend of _.reject
, because it removes any element the predicate
returns truthy for, but it mutates the array.
It's not the most trivial thing to implement if you want to remove all matches cause of splice. Quick port based on MooTools docs
_.deleteWhere = function(list, what) {
var predicate = _.iteratee(what), index = this.length;
while(index--) {
if (predicate(list[index], index, list) this.splice(index,1);
}
return list;
}
The name _.deleteWhere
is a bit gross. You don't have _.filterWhere
or _.rejectWhere
and _.delete
on its own may require brackets, _['delete']
in some environments which is why I prefer _.remove
.
Problem is iteratee won't work here, because you could be passing a hash of properties to match against, or you could be passing an object to compare by ref equality (or string, etc).
There were plenty of things mootools did because they didn't know any better. One of Underscores greatest strengths is a terse API, and it becomes hard to get rid of methods this once it's added.
Problem is iteratee won't work here
Naw, think of it like _.reject
, but instead of returning a new array, it returns the mutated array.
One of Underscores greatest strengths is a terse API, and it becomes hard to get rid of methods this once it's added.
Open it up to a poll. Jeremy could tweet the poll (I'm sure there's a nice poll service somewhere) and then see if there's an opinion one way or the other from users.
My bad. That was unnecessary. But keeping a level-headed and intelligent design philosophy is essential in as small a library as underscore.
Design by committee. Brilliant!
It's simply testing the waters to see if Underscore's users have a strong opinion one way or another. It's a data point to consider when determining if something like this is a good fit for Underscore.
I find methods like _.remove
useful, but maybe others don't. I can see being hesitant about expanding mutator methods beyond _#pop
, _#push
, _#shift
, _#splice
, & _#unshift
because it's not something Underscore has tackled. In 2 years I've only added 2 array mutator methods (_.pull
& _.remove
).
Bumping this because I ran into the need for it again today,
var Layer = Backbone.Model.extend({}, {
isValid(settings) {
return _.has(settings, "layerType");
}
});
var LayerCollection = Backbone.Collection.extend({
model: Layer,
initialize(layers) {
_.remove(layers, _.negate(Layer.isValid));
}
});
new LayerModel([
{name: "layer1", layerType: "position"},
{name: "layer2", layerType: "path"},
{name: "invalid"}
]);
Sure @megawac -- go for it. _.remove
is a fine name.