Reputation: 875
I am trying to use underscore.js _.map
function on an array of objects, to get an array with a property of each object. That's the usual scenario, so :
var finalArray = _.map(myArray, function(obj) {
return obj.myProperty;
});
But in some cases I need that nothing be added in the array. It could be something like :
var finalArray = _.map(myArray, function(obj) {
if (!obj.ignore) {
return obj.myProperty;
}
});
The result of this is that an undefined
value is pushed into the array, which is not the same as not pushing anything at all.
Is there a way for the map function not to push a value, or do I need to post-process my finalArray
to remove the unwanted undefined
's?
Upvotes: 32
Views: 43427
Reputation: 1607
Try using lodash's compact()
. It creates an array with all falsey values removed. Thus, the values false
, null
, 0
, ""
, undefined
, and NaN
are removed.
https://lodash.com/docs#compact
I'm using it—it's very clean.
Upvotes: 3
Reputation: 10857
Here's another way. This one makes use of the compose function in underscore. Why compose? compose is backed by Category theory in Mathematics. This way is also point-free.
var pluckMyProp = function(array) {
return _.pluck(array, 'myProperty')
}
var reject = function(array) {
return _.reject(array, function(element) {
return element['ignore'] === true
})
}
var finalArray = _.compose(pluckMyProp, reject)
var data = [{myProperty: 1, ignore: false}, {ignore: true}, {myProperty: 2}]
finalArray(data) //=> [1,2]
Upvotes: 0
Reputation: 44917
This can be done using Underscore methods alone, points-free style:
var finalArray = _.chain(myArray)
.reject('ignore')
.pluck('myProperty')
.value();
Upvotes: 14
Reputation: 995
You could use reduce:
myArray.reduce(function (acc, obj) {
if (!obj.ignore) {
acc.push(obj.myProperty);
}
return acc;
}, []);
or with lodash:
_.reduce(myArray, function (acc, obj) {
if (!obj.ignore) {
acc.push(obj.myProperty);
}
return acc;
}, []);
Upvotes: 31
Reputation: 47099
.map
will map out a new value to the array, you can use .filter
to filter the array. FYI you can use .pluck
to map a property from an object:
_.chain(myArray).filter(function(obj) { return !obj.ignore; }).pluck('myProperty').value();
You can also use .where
like this:
_.chain(myArray).where({ignore: false}).pluck('myProperty').value();
Or:
_.pluck(_.where(myArray, {ignore: false}), 'myProperty');
Upvotes: 5
Reputation: 591
you should use _.filter() before _.map()
var filteredArray = _.filter(myArray,function(obj) {
return !obj.ignore;
});
var finalArray = _.map(filteredArray, function(obj) {
return obj.myProperty;
});
Upvotes: 32
Reputation: 6052
So this means you want to filter, then map your array.
To do this in underscore
way, you will need to pass your array into this pipeline:
myArray --> filter --> map --> finalArray
var isIncluded = function(obj){
return !obj.ignore
}
var takeProperty = function(obj){
return obj.myProperty
}
var finalArray = _.map( _.filter(myArray, isIncluded), takeProperty );
Upvotes: 1