lodash-contrib
Version:
The brass buckles on lodash's utility belt
100 lines (81 loc) • 3.46 kB
JavaScript
module.exports = function(_) {
// Create quick reference variables for speed access to core prototypes.
var slice = Array.prototype.slice,
concat = Array.prototype.concat;
var existy = function(x) { return x != null; };
var truthy = function(x) { return (x !== false) && existy(x); };
var isSeq = function(x) { return (_.isArray(x)) || (_.isArguments(x)); };
function nths(array, indices) {
if (array == null) return void 0;
if (isSeq(indices))
return _(indices).map(function(i){return array[i];}).valueOf();
else
return nths(array, slice.call(arguments, 1));
}
// Mixing in the array selectors
// ----------------------------
_.mixin({
// Returns the second element of an array. Passing **n** will return all but
// the first of the head N values in the array. The **guard** check allows it
// to work with `_.map`.
second: function(array, n, guard) {
if (array == null) return void 0;
return (n != null) && !guard ? slice.call(array, 1, n) : array[1];
},
// Returns the third element of an array. Passing **n** will return all but
// the first two of the head N values in the array. The **guard** check allows it
// to work with `_.map`.
third: function(array, n, guard) {
if (array == null) return void 0;
return (n != null) && !guard ? slice.call(array, 2, n) : array[2];
},
// A function to get at an index into an array
nth: function(array, index, guard) {
if ((index != null) && !guard) return array[index];
},
// A function to get values via indices into an array
nths: nths,
valuesAt: nths,
// A function to get at "truthily" indexed values
// bin refers to "binary" nature of true/false values in binIndices
// but can also be thought of as putting array values into either "take" or "don't" bins
binPick: function binPick(array, binIndices) {
if (array == null) return void 0;
if (isSeq(binIndices))
return _.nths(array, _.range(binIndices.length).filter(function(i){return binIndices[i];}));
else
return binPick(array, slice.call(arguments, 1));
},
// Returns an array with two internal arrays built from
// taking an original array and spliting it at the index
// where a given function goes falsey.
splitWith: function(array, pred) {
return [_.takeWhile(array, pred), _.dropWhile(array, pred)];
},
// Takes an array and partitions it as the given predicate changes
// truth sense.
partitionBy: function(array, fun){
if (_.isEmpty(array) || !existy(array)) return [];
var fst = _.first(array);
var fstVal = fun(fst);
var run = concat.call([fst], _.takeWhile(_.rest(array), function(e) {
return _.isEqual(fstVal, fun(e));
}));
return concat.call([run], _.partitionBy(_.drop(array, _.size(run)), fun));
},
// Returns the 'best' value in an array based on the result of a
// given function.
best: function(array, fun) {
return _.reduce(array, function(x, y) {
return fun(x, y) ? x : y;
});
},
// Returns an array of existy results of a function over an source array.
keep: function(array, fun) {
if (!isSeq(array)) throw new TypeError("expected an array as the first argument");
return _.filter(_.map(array, function(e) {
return fun(e);
}), existy);
}
});
};