This is real JavaScript/Lodash code used in a project I'm currently working on, but actually this particular question bothers me quite often regardless of the language. Say, I need to generate some data relying on some filtered out piece of other date.
Here are three approaches:
// filtering out, then just map
var activityFields =
_.map(
_.pick(options, function(val, key) {return val && userData[key]}),
function(val, key) {
return ({name: val, value: userData[key]})
}
);
// map all, then just filter out what you need
var activityFields =
_.filter(
_.map(options, function(val, key) {
return {name: val, value: userData[key]}
}), function(item) {
return item.name && item.value;
}
);
// being more imperative
var activityFields = [];
_.each(options, function(val, key) {
if (val && userData[key]) {
activityFields.push({name: val, value: userData[key]})
}
});
Which one is to better for making an idiom? I caught myself using them interchangeably.
1 Answer 1
The mapping step is pointless for something that will be filtered out anyway. Logically, mapping first and filtering later is a waste of CPU cycles. It's also confusing to read, as I tend to give programmers the benefit of the doubt, so when something looks pointless, I have to double check if I'm missing something.
Functional solutions are ideal. They naturally avoid side effects, naturally lead to better encapsulation, and they go hand in hand with immutability and parallelism. Imperative solutions can be useful when the functional approach would be hard to read somehow, or not efficient due to creating too many objects. That's not the case here, the imperative solution had no benefit whatsoever.
In the posted code, among the given alternatives, the first (pick + map) is a clear winner.
Explore related questions
See similar questions with these tags.
.filter(.map())
, and the other mentions filtering, then mapping, while the code goes.map(.pick())
\$\endgroup\$