I have a function, which maps an array with underscore
. Here is the function:
var services = _.map(userCopy.get('services'), function (service) {
if (service.service_selected === true) {
return service;
}
});
My problem is that when the conditional === false
, then I get undefined
put into services
. Of course I can remove the undefined
, but that is ugly and I just want to use map
correctly. How do I fix this?
To not return undefined values from the map() method, you have to explicitly return a value from the callback function you passed to map() .
A variable that has not been assigned a value is of type undefined . A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value. A function returns undefined if a value was not returned .
Updated my answer... This solved my problem
var missingParamsArray = _.map(requiredParams, function (val, param) {
if (val) {
if (!req.user[param]) {
return param;
}
}
});
var missingParams = _.filter(missingParamsArray, Boolean);
missingParams can also be written as
var missingParams = _.filter(missingParamsArray, function (param) {
return param !== undefined;
});
_.map
uses whatever the function returns, to build the result. If a function doesn't return anything explicitly, JavaScript returns undefined
. That's why the result of _.map
has undefined
whenever the condition fails.
What you actually need, is a _.filter
var services = _.filter(userCopy.get('services'), function(service) {
return service.service_selected === true;
});
_.filter
accepts a collection and a predicate function. It applies the predicate function to each and every value of the collection and if the function returns true
, that element will be included in the result, if the function returns false
, that element will be skipped.
Note: You can actually use _.matcher
, along with _.filter
, like this
var isServiceSelected = _.matcher({
service_selected: true;
});
var services = _.filter(userCopy.get('services'), isServiceSelected);
This will be very useful if you are going to filter based on service_selected: true
condition more than once. If it is just a one-time thing, then _.where
shown below would be better alternative.
You can also use _.where
, which can return the objects only if the current object contains all the key-value pairs listed, like this
var services = _.where(userCopy.get('services'), {
service_selected: true;
});
Now, all the service objects will be returned which have service_selected
attribute value as true
.
Demo:
function display(heading, data) {
var json = JSON.stringify(data, null, 4);
document.body.appendChild(document.createElement('h3')).innerHTML = heading;
document.body.appendChild(document.createElement('pre')).innerHTML = json;
}
var data = [{
"name": "auth",
"service_selected": true
}, {
"name": "authorization",
"service_selected": false
}, {
"name": "faltu",
"service_selected": true
}];
display("_.filter", _.filter(data, function (service) {
return service.service_selected === true;
}));
display("_.matcher", _.filter(data, _.matcher({
service_selected: true
})));
display("_.where", _.where(data, {
service_selected: true
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With