Remove empty properties / falsy values from Object with Underscore.js
With lodash's transform,
_.transform(obj, function(res, v, k) {
if (v) res[k] = v;
});
Since Underscore version 1.7.0, you can use _.pick
:
_.pick(sourceObj, _.identity)
Explanation
The second parameter to _.pick
can be a predicate function for selecting values. Values for which the predicate returns truthy are picked, and values for which the predicate returns falsy are ignored.
pick _.pick(object, *keys)
Return a copy of the object, filtered to only have values for the whitelisted keys (or array of valid keys). Alternatively accepts a predicate indicating which keys to pick.
_.identity
is a helper function that returns its first argument, which means it also works as a predicate function that selects truthy values and rejects falsy ones. The Underscore library also comes with a bunch of other predicates, for instance _.pick(sourceObj, _.isBoolean)
would retain only boolean properties.
If you use this technique a lot, you might want to make it a bit more expressive:
var pickNonfalsy = _.partial(_.pick, _, _.identity); // Place this in a library module or something
pickNonfalsy(sourceObj);
Underscore version 1.6.0 provided _.pick
as well, but it didn't accept a predicate function instead of a whitelist.
Quick 'n Clear: _.omitBy( source, i => !i );
This is stated in an inverse fashion to Emil's answer. This way imho reads clearer; it's more self explanatory.
Slightly less clean if you don't have the luxury of ES6: _.omitBy( source, function(i){return !i;});
Alternate: _.omitBy( source, _.isEmpty)
Using _.isEmpty
, instead of _.identity
for truthiness, will also conveniently remove empty arrays and objects from the collection and perhaps inconveniently remove numbers and dates. Thus the outcome is NOT an exact answer to the OP's question, however it could be useful when looking to remove empty collections.
You could make your own underscore plugin (mixin) :
_.mixin({
compactObject: function(o) {
_.each(o, function(v, k) {
if(!v) {
delete o[k];
}
});
return o;
}
});
And then use it as a native underscore method :
var o = _.compactObject({
foo: 'bar',
a: 0,
b: false,
c: '',
d: null,
e: undefined
});
Update
As @AndreiNeculau pointed out, this mixin affects the original object, while the original compact
underscore method returns a copy of the array.
To solve this issue and make our compactObject
behave more like it's cousin, here's a minor update:
_.mixin({
compactObject : function(o) {
var clone = _.clone(o);
_.each(clone, function(v, k) {
if(!v) {
delete clone[k];
}
});
return clone;
}
});