Underscore.js _.map function : skip a value

43.2k Views Asked by At

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?

7

There are 7 best solutions below

2
On BEST ANSWER

you should use _.filter() before _.map()

var filteredArray = _.filter(myArray,function(obj) {
     return !obj.ignore;
});

var finalArray = _.map(filteredArray, function(obj) {
    return obj.myProperty;
});
2
On

This can be done using Underscore methods alone, points-free style:

var finalArray = _.chain(myArray)
    .reject('ignore')
    .pluck('myProperty')
    .value();
1
On

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]
2
On

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  );
0
On

.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');
2
On

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;
}, []);
0
On

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.