Certain array functions like compact(), difference(), and without() Back

There are some interesting array functions that will be discussed here like compact(), difference(), and without().

Firstly, according to the implementation of _.compact(), it's not hard to know that this method is always used to filter out false from an array.

_.compact = function(array) {
    return _.filter(array, _.identity);
};

_.filter() is similar to Array.prototype.filter(), and it's used to filter out some elements under a given condition, as the function _.identity describes. If this function accepts an element of the array and return a true value, then the element can be kept into the array.

_.identity = function(value) {
    return value;
};

Both _.without() and _.difference() is used to filter out some elements from an array with given specific values:

var arr = [1, 2, 3, 4, 5];
var result = _.without(arr, 1, 2, 3);
console.log(result); /** => [4, 5] */
var arr = [1, 2, 3, 4, 5];
var result = _.difference(arr, [1, 2, 3], [5, 6]);
console.log(result); /** => [4] */

The difference between these two methods is that _.without() will accept single values separated by a comma, while _.difference() will accept values constructed with arrays. Therefore, if we have implemented _.difference(), we can just implement _.without() by calling _.difference() after putting arguments into an array:

/** _.difference(array, *others) */
_.difference = function(array) {
    /**
     * because the `strict` property has accepted `true`, an argument like 10 when 
     * calling _.difference(arr, [1, 2], 10); will be ignored
     */
    var rest = flatten(arguments, true, true, 1);

    /** use `_.filter()` to filter out */
    return _.filter(array, function(value) {
        return !_.contains(rest, value);
    });
};

_.without = function(array) {
    /** put arguments except the given array into an array */
    return _.difference(array, slice.call(arguments, 1));
};

How about implementing it in a reversed way (we have to consider more about arguments when calling both of them):

_.without = function(array) {
    var rest = (this == 'difference') ? _.flatten(arguments, false, false, 1) : Array.prototype.slice.call(arguments, 1);

    return _.filter(array, function(value) {
        return !_.contains(rest, value);
    });
};

_.difference = function(array) {
    /** filter out arguments which is not an array firstly */
    var args = _.flatten(arguments, true, true, 1);

    /**
     * let the method `_.without()` know that whether it's called by `_.difference()`,
     * if so, then flatten all the arrays from argments,
     * if not, then do not flatten.
     */
    return _.without.apply('difference', args.unshift(array));
};

results matching ""

    No results matching ""