lodash-contrib
Advanced tools
Comparing version 241.4.4 to 241.4.5
@@ -46,7 +46,4 @@ // lodash-contrib (lodash.function.combinators.js 0.0.1) | ||
_.mixin({ | ||
// Takes a value and returns a function that always returns | ||
// said value. | ||
always: function(value) { | ||
return function() { return value; }; | ||
}, | ||
// Provide "always" alias for backwards compatibility | ||
always: _.constant, | ||
@@ -111,3 +108,3 @@ // Takes some number of functions, either as an array or variadically | ||
return function() { | ||
return !pred.apply(null, arguments); | ||
return !pred.apply(this, arguments); | ||
}; | ||
@@ -122,3 +119,3 @@ }, | ||
return function(array) { | ||
return fun.apply(null, array); | ||
return fun.apply(this, array); | ||
}; | ||
@@ -189,4 +186,4 @@ }, | ||
return _.map(funs, function(f) { | ||
return f.apply(null, args); | ||
}); | ||
return f.apply(this, args); | ||
}, this); | ||
}; | ||
@@ -211,3 +208,3 @@ }, | ||
return fun.apply(null, args); | ||
return fun.apply(this, args); | ||
}; | ||
@@ -223,3 +220,3 @@ }, | ||
return fun.apply(null, flipped); | ||
return fun.apply(this, flipped); | ||
}; | ||
@@ -233,3 +230,3 @@ }, | ||
return fun.apply(null, reversed); | ||
return fun.apply(this, reversed); | ||
}; | ||
@@ -236,0 +233,0 @@ }, |
@@ -18,7 +18,27 @@ // lodash-contrib (lodash.util.strings.js 0.0.1) | ||
var plusRegex = /\+/g; | ||
var spaceRegex = /\%20/g; | ||
var bracketRegex = /(?:([^\[]+))|(?:\[(.*?)\])/g; | ||
var urlDecode = function (s) { | ||
var urlDecode = function(s) { | ||
return decodeURIComponent(s.replace(plusRegex, '%20')); | ||
}; | ||
var urlEncode = function(s) { | ||
return encodeURIComponent(s).replace(spaceRegex, '+'); | ||
}; | ||
var buildParams = function(prefix, val, top) { | ||
if (_.isUndefined(top)) top = true; | ||
if (_.isArray(val)) { | ||
return _.map(val, function(value, key) { | ||
return buildParams(top ? key : prefix + '[]', value, false); | ||
}).join('&'); | ||
} else if (_.isObject(val)) { | ||
return _.map(val, function(value, key) { | ||
return buildParams(top ? key : prefix + '[' + key + ']', value, false); | ||
}).join('&'); | ||
} else { | ||
return urlEncode(prefix) + '=' + urlEncode(val); | ||
} | ||
}; | ||
// Mixing in the string utils | ||
@@ -29,3 +49,3 @@ // ---------------------------- | ||
// Explodes a string into an array of chars | ||
explode: function (s) { | ||
explode: function(s) { | ||
return s.split(''); | ||
@@ -36,9 +56,45 @@ }, | ||
fromQuery: function(str) { | ||
var obj = str.split('&').reduce(function (seed, param) { | ||
var pair = param.split('='); | ||
var key = urlDecode(pair[0]); | ||
var val = urlDecode(pair[1]); | ||
seed[key] = val; | ||
return seed; | ||
}, {}); | ||
var parameters = str.split('&'), | ||
obj = {}, | ||
parameter, | ||
key, | ||
match, | ||
lastKey, | ||
subKey, | ||
depth; | ||
// Iterate over key/value pairs | ||
_.each(parameters, function(parameter) { | ||
parameter = parameter.split('='); | ||
key = urlDecode(parameter[0]); | ||
lastKey = key; | ||
depth = obj; | ||
// Reset so we don't have issues when matching the same string | ||
bracketRegex.lastIndex = 0; | ||
// Attempt to extract nested values | ||
while ((match = bracketRegex.exec(key)) !== null) { | ||
if (!_.isUndefined(match[1])) { | ||
// If we're at the top nested level, no new object needed | ||
subKey = match[1]; | ||
} else { | ||
// If we're at a lower nested level, we need to step down, and make | ||
// sure that there is an object to place the value into | ||
subKey = match[2]; | ||
depth[lastKey] = depth[lastKey] || (subKey ? {} : []); | ||
depth = depth[lastKey]; | ||
} | ||
// Save the correct key as a hash or an array | ||
lastKey = subKey || _.size(depth); | ||
} | ||
// Assign value to nested object | ||
depth[lastKey] = urlDecode(parameter[1]); | ||
}); | ||
return obj; | ||
@@ -48,3 +104,3 @@ }, | ||
// Implodes and array of chars into a string | ||
implode: function (a) { | ||
implode: function(a) { | ||
return a.join(''); | ||
@@ -54,15 +110,11 @@ }, | ||
// Converts a string to camel case | ||
camelCase: function (string) { | ||
return string.replace(/-([a-z])/g, function (g) { | ||
return g[1].toUpperCase(); | ||
}); | ||
camelCase : function( string ){ | ||
return string.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); | ||
}, | ||
// Converts camel case to dashed (opposite of _.camelCase) | ||
toDash: function (string) { | ||
string = string.replace(/([A-Z])/g, function ($1) { | ||
return "-" + $1.toLowerCase(); | ||
}); | ||
toDash : function( string ){ | ||
string = string.replace(/([A-Z])/g, function($1){return "-"+$1.toLowerCase();}); | ||
// remove first dash | ||
return ( string.charAt(0) == '-' ) ? string.substr(1) : string; | ||
return ( string.charAt( 0 ) == '-' ) ? string.substr(1) : string; | ||
}, | ||
@@ -72,10 +124,7 @@ | ||
toQuery: function(obj) { | ||
var parameters = _.map(obj, function (v, k) { | ||
return encodeURIComponent(k) + '=' + encodeURIComponent(v); | ||
}); | ||
return parameters.join('&'); | ||
return buildParams('', obj); | ||
}, | ||
// Reports whether a string contains a search string. | ||
strContains: function (str, search) { | ||
strContains: function(str, search) { | ||
if (typeof str != 'string') throw new TypeError; | ||
@@ -119,1 +168,2 @@ return (str.indexOf(search) != -1); | ||
})(this); | ||
@@ -54,7 +54,7 @@ // lodash-contrib v241.2.0 | ||
// Takes an array and parititions it some number of times into | ||
// Takes an array and chunks it some number of times into | ||
// sub-arrays of size n. Allows and optional padding array as | ||
// the third argument to fill in the tail partition when n is | ||
// not sufficient to build paritions of the same size. | ||
partition: function(array, n, pad) { | ||
// the third argument to fill in the tail chunk when n is | ||
// not sufficient to build chunks of the same size. | ||
chunk: function(array, n, pad) { | ||
var p = function(array) { | ||
@@ -76,7 +76,7 @@ if (array == null) return []; | ||
// Takes an array and parititions it some number of times into | ||
// Takes an array and chunks it some number of times into | ||
// sub-arrays of size n. If the array given cannot fill the size | ||
// needs of the final partition then a smaller partition is used | ||
// needs of the final chunk then a smaller chunk is used | ||
// for the last. | ||
partitionAll: function(array, n, step) { | ||
chunkAll: function(array, n, step) { | ||
step = (step != null) ? step : n; | ||
@@ -770,7 +770,4 @@ | ||
_.mixin({ | ||
// Takes a value and returns a function that always returns | ||
// said value. | ||
always: function(value) { | ||
return function() { return value; }; | ||
}, | ||
// Provide "always" alias for backwards compatibility | ||
always: _.constant, | ||
@@ -835,3 +832,3 @@ // Takes some number of functions, either as an array or variadically | ||
return function() { | ||
return !pred.apply(null, arguments); | ||
return !pred.apply(this, arguments); | ||
}; | ||
@@ -846,3 +843,3 @@ }, | ||
return function(array) { | ||
return fun.apply(null, array); | ||
return fun.apply(this, array); | ||
}; | ||
@@ -913,4 +910,4 @@ }, | ||
return _.map(funs, function(f) { | ||
return f.apply(null, args); | ||
}); | ||
return f.apply(this, args); | ||
}, this); | ||
}; | ||
@@ -935,3 +932,3 @@ }, | ||
return fun.apply(null, args); | ||
return fun.apply(this, args); | ||
}; | ||
@@ -947,3 +944,3 @@ }, | ||
return fun.apply(null, flipped); | ||
return fun.apply(this, flipped); | ||
}; | ||
@@ -957,3 +954,3 @@ }, | ||
return fun.apply(null, reversed); | ||
return fun.apply(this, reversed); | ||
}; | ||
@@ -1957,2 +1954,29 @@ }, | ||
// No reason to create regex more than once | ||
var plusRegex = /\+/g; | ||
var spaceRegex = /\%20/g; | ||
var bracketRegex = /(?:([^\[]+))|(?:\[(.*?)\])/g; | ||
var urlDecode = function(s) { | ||
return decodeURIComponent(s.replace(plusRegex, '%20')); | ||
}; | ||
var urlEncode = function(s) { | ||
return encodeURIComponent(s).replace(spaceRegex, '+'); | ||
}; | ||
var buildParams = function(prefix, val, top) { | ||
if (_.isUndefined(top)) top = true; | ||
if (_.isArray(val)) { | ||
return _.map(val, function(value, key) { | ||
return buildParams(top ? key : prefix + '[]', value, false); | ||
}).join('&'); | ||
} else if (_.isObject(val)) { | ||
return _.map(val, function(value, key) { | ||
return buildParams(top ? key : prefix + '[' + key + ']', value, false); | ||
}).join('&'); | ||
} else { | ||
return urlEncode(prefix) + '=' + urlEncode(val); | ||
} | ||
}; | ||
// Mixing in the string utils | ||
@@ -1967,2 +1991,50 @@ // ---------------------------- | ||
// Parses a query string into a hash | ||
fromQuery: function(str) { | ||
var parameters = str.split('&'), | ||
obj = {}, | ||
parameter, | ||
key, | ||
match, | ||
lastKey, | ||
subKey, | ||
depth; | ||
// Iterate over key/value pairs | ||
_.each(parameters, function(parameter) { | ||
parameter = parameter.split('='); | ||
key = urlDecode(parameter[0]); | ||
lastKey = key; | ||
depth = obj; | ||
// Reset so we don't have issues when matching the same string | ||
bracketRegex.lastIndex = 0; | ||
// Attempt to extract nested values | ||
while ((match = bracketRegex.exec(key)) !== null) { | ||
if (!_.isUndefined(match[1])) { | ||
// If we're at the top nested level, no new object needed | ||
subKey = match[1]; | ||
} else { | ||
// If we're at a lower nested level, we need to step down, and make | ||
// sure that there is an object to place the value into | ||
subKey = match[2]; | ||
depth[lastKey] = depth[lastKey] || (subKey ? {} : []); | ||
depth = depth[lastKey]; | ||
} | ||
// Save the correct key as a hash or an array | ||
lastKey = subKey || _.size(depth); | ||
} | ||
// Assign value to nested object | ||
depth[lastKey] = urlDecode(parameter[1]); | ||
}); | ||
return obj; | ||
}, | ||
// Implodes and array of chars into a string | ||
@@ -1989,4 +2061,9 @@ implode: function (a) { | ||
// Creates a query string from a hash | ||
toQuery: function(obj) { | ||
return buildParams('', obj); | ||
}, | ||
// Reports whether a string contains a search string. | ||
strContains: function (str, search) { | ||
strContains: function(str, search) { | ||
if (typeof str != 'string') throw new TypeError; | ||
@@ -1993,0 +2070,0 @@ return (str.indexOf(search) != -1); |
@@ -5,2 +5,4 @@ ### array.builders | ||
-------------------------------------------------------------------------------- | ||
#### cat | ||
@@ -12,16 +14,18 @@ | ||
_.cat(); // 0-args | ||
//=> [] | ||
```javascript | ||
_.cat(); // 0-args | ||
//=> [] | ||
_.cat([]); // 1-arg, empty array | ||
//=> [] | ||
_.cat([]); // 1-arg, empty array | ||
//=> [] | ||
_.cat([1,2,3]); // 1-arg | ||
//=> [1,2,3] | ||
_.cat([1,2,3]); // 1-arg | ||
//=> [1,2,3] | ||
_.cat([1,2,3],[4,5,6]); // 2-args | ||
//=> [1,2,3,4,5,6] | ||
_.cat([1,2,3],[4,5,6]); // 2-args | ||
//=> [1,2,3,4,5,6] | ||
_.cat([1,2,3],[4,5,6],[7]); // 3+ args | ||
//=> [1,2,3,4,5,6,7] | ||
_.cat([1,2,3],[4,5,6],[7]); // 3+ args | ||
//=> [1,2,3,4,5,6,7] | ||
``` | ||
@@ -32,4 +36,6 @@ Not every argument to `_.cat` needs to be an array; other types are accepted. | ||
_.cat(1,[2],3,4); // mixed args | ||
//=> [1,2,3,4] | ||
```javascript | ||
_.cat(1,[2],3,4); // mixed args | ||
//=> [1,2,3,4] | ||
``` | ||
@@ -40,7 +46,11 @@ The `_.cat` function will also work with the `arguments` object as if it were an array. | ||
function f(){ return _.cat(arguments, 4,5,6); } | ||
```javascript | ||
function f(){ return _.cat(arguments, 4,5,6); } | ||
f(1,2,3); | ||
//=> [1,2,3,4,5,6] | ||
f(1,2,3); | ||
//=> [1,2,3,4,5,6] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### chunk | ||
@@ -50,20 +60,30 @@ | ||
_.chunk([0,1,2,3], 2); | ||
//=> , [[0,1],[2,3]] | ||
```javascript | ||
_.chunk([0,1,2,3], 2); | ||
//=> , [[0,1],[2,3]] | ||
``` | ||
If the original array cannot completely fulfill the chunk scheme then the array returned will drop the undersized final chunk: | ||
_.chunk([0,1,2,3,4], 2); | ||
//=> , [[0,1],[2,3]] | ||
```javascript | ||
_.chunk([0,1,2,3,4], 2); | ||
//=> , [[0,1],[2,3]] | ||
``` | ||
You can pass an optional third argument to `_.chunk` to pad out the final array chunk should it fall short. If the value given as the third argument is *not* an array then it is repeated the needed number of times: | ||
_.chunk([0,1,2,3,4], 3, '_'); | ||
//=> , [[0,1,2],[3,'_','_']] | ||
```javascript | ||
_.chunk([0,1,2,3,4], 3, '_'); | ||
//=> , [[0,1,2],[3,'_','_']] | ||
``` | ||
If you given an array as the optional third argument then that array is used to pad in-place as needed: | ||
_.chunk([0,1,2,3,4], 3, ['a', 'b']); | ||
//=> , [[0,1,2],[3,'a','b']] | ||
```javascript | ||
_.chunk([0,1,2,3,4], 3, ['a', 'b']); | ||
//=> , [[0,1,2],[3,'a','b']] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### chunkAll | ||
@@ -73,10 +93,15 @@ | ||
_.chunkAll([0,1,2,3,4], 3); | ||
//=> , [[0,1,2],[3]] | ||
```javascript | ||
_.chunkAll([0,1,2,3,4], 3); | ||
//=> , [[0,1,2],[3]] | ||
``` | ||
Also, `_.chunkAll` takes an optional third argument signifying that paritions should be built from skipped regions: | ||
_.chunkAll(_.range(1), 2, 4); | ||
//=> [[0,1],[4,5],[8,9]] | ||
```javascript | ||
_.chunkAll(_.range(1), 2, 4); | ||
//=> [[0,1],[4,5],[8,9]] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
@@ -89,10 +114,12 @@ #### cons | ||
_.cons(0, []); | ||
//=> [0] | ||
```javascript | ||
_.cons(0, []); | ||
//=> [0] | ||
_.cons(1, [2]); | ||
//=> [1,2] | ||
_.cons(1, [2]); | ||
//=> [1,2] | ||
_.cons([0], [1,2,3]); | ||
//=> [0,1,2,3] | ||
_.cons([0], [1,2,3]); | ||
//=> [0,1,2,3] | ||
``` | ||
@@ -103,7 +130,9 @@ The `_.cons` function also can be used to create pairs if the second argument is not an array. | ||
_.cons(1, 2); | ||
//=> [1,2] | ||
```javascript | ||
_.cons(1, 2); | ||
//=> [1,2] | ||
_.cons([1], 2); | ||
//=> [[1],2] | ||
_.cons([1], 2); | ||
//=> [[1],2] | ||
``` | ||
@@ -114,7 +143,8 @@ Finally, `_.cons` will operate with the `arguments` object. | ||
function f() { return _.cons(0, arguments) } | ||
```javascript | ||
function f() { return _.cons(0, arguments) } | ||
f(1,2,3); | ||
//=> [0,1,2,3] | ||
f(1,2,3); | ||
//=> [0,1,2,3] | ||
``` | ||
#### partition | ||
@@ -154,24 +184,15 @@ | ||
-------------------------------------------------------------------------------- | ||
#### mapcat | ||
#### cycle | ||
There are times when a mapping operation produces results contained in arrays, but the final result should be flattened one level. For these circumstances you can use `_.mapcat` to produce results: | ||
The `_.cycle` function takes an integer value used to build an array of that size containing the number of iterations through the given array, strung end-to-end as many times as needed. An example is probably more instructive: | ||
var array = [1,2,null,4,undefined,6]; | ||
```javascript | ||
_.cycle(5, [1,2,3]); | ||
//=> [1,2,3,1,2] | ||
``` | ||
var errors = _.mapcat(array, function(e,i) { | ||
if (e == null) { | ||
return ["Element @" + i + " is bad"]; | ||
} | ||
else { | ||
return []; | ||
} | ||
}); | ||
-------------------------------------------------------------------------------- | ||
Inspecting the contents of `errors` shows: | ||
["Element @2 is bad", "Element @4 is bad"] | ||
The `_.mapcat` function is equivalent to `_.cat.apply(array, _.map(array,fun))`. | ||
#### interpose | ||
@@ -181,123 +202,185 @@ | ||
_.interpose([1,2,3], 0); | ||
//=> [1,0,2,0,3] | ||
```javascript | ||
_.interpose([1,2,3], 0); | ||
//=> [1,0,2,0,3] | ||
``` | ||
If there are no betweens (i.e. empty and single-element arrays), then the original array is returned: | ||
_.interpose([1], 0); | ||
//=> [1] | ||
```javascript | ||
_.interpose([1], 0); | ||
//=> [1] | ||
_.interpose([], 0); | ||
//=> [] | ||
_.interpose([], 0); | ||
//=> [] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### weave | ||
#### iterateUntil | ||
The `_.weave` function works similarly to `_.interpose` (shown above) except that it accepts an array used as the interposition values. In other words, `_.weave` takes two arrays and returns a new array with the original elements woven together. An example would help: | ||
The `_.iterateUntil` function takes a function used as a result generator, a function used as a stop-check and a seed value and returns an array of each generated result. The operation of `_.iterateUntil` is such that the result generator is passed the seed to start and each subsequent result which will continue **until** a result fails the check function (i.e. returns falsey). An example is best: | ||
_.weave(['a','b','c'], [1,2,3]); | ||
//=> ['a',1,'b',2,'c',3] | ||
```javascript | ||
var dec = function(n) { return n - 1; }; | ||
var isPos = function(n) { return n > 0; }; | ||
``` | ||
The array returned from `_.weave` will be as long as the longest array given with the woven entries stopping according to the shortest array: | ||
The `dec` result generator takes a number and decrements it by one. The `isPos` predicate takes a number and returns `true` if it's positive. Using these two functions you can build an array of every number from `6` to `0`, inclusive: | ||
_.weave(['a','b','c'], [1]); | ||
//=> ['a',1,'b','c'] | ||
```javascript | ||
_.iterateUntil(dec, isPos, 6); | ||
//=> [5,4,3,2,1] | ||
``` | ||
The `_.interleave` function is an alias for `_.weave`. | ||
That is, the array only contains every number from `5` down to `1` because when the result of `dec` got to `0` the `isPos` check failed (i.e. went falsey) thus terminating the execution. | ||
#### repeat | ||
-------------------------------------------------------------------------------- | ||
Signature: `_.repeat(t:Integer, value:Any)` | ||
#### keepIndexed | ||
The `_.repeat` function takes an integer value used to build an array of that size containing the value given: | ||
The `_.keepIndexed` function takes an array and a function and returns a new array filled with the *non-null* return results of the given function on the elements or keys in the given array: | ||
_.repeat(5, 'a'); | ||
//=> ['a','a','a','a','a'] | ||
```javascript | ||
_.keepIndexed([1,2,3], function(k) { | ||
return i === 1 || i === 2; | ||
}); | ||
#### cycle | ||
//=> [false, true, true] | ||
``` | ||
The `_.cycle` function takes an integer value used to build an array of that size containing the number of iterations through the given array, strung end-to-end as many times as needed. An example is probably more instructive: | ||
If you return either `null` or `undefined` then the result is dropped from the resulting array: | ||
_.cycle(5, [1,2,3]); | ||
//=> [1,2,3,1,2] | ||
```javascript | ||
_.keepIndexed(['a','b','c'], function(k, v) { | ||
if (k === 1) return v; | ||
}); | ||
#### splitAt | ||
//=> ['b'] | ||
``` | ||
The `_.splitAt` function takes an array and a numeric index and returns a new array with two embedded arrays representing a split of the original array at the index provided: | ||
-------------------------------------------------------------------------------- | ||
_.splitAt([1,2,3,4,5], 2); | ||
//=> [[1,2],[3,4,5]] | ||
#### mapcat | ||
_.splitAt([1,2,3,4,5], 0); | ||
//=> [[],[1,2,3,4,5]] | ||
There are times when a mapping operation produces results contained in arrays, but the final result should be flattened one level. For these circumstances you can use `_.mapcat` to produce results: | ||
The operation of `_.splitAt` is safe if the index provided is outside the range of legal indices: | ||
```javascript | ||
var array = [1,2,null,4,undefined,6]; | ||
_.splitAt([1,2,3,4,5], 20000); | ||
//=> [[1,2,3,4,5],[]] | ||
var errors = _.mapcat(array, function(e,i) { | ||
if (e == null) { | ||
return ["Element @" + i + " is bad"]; | ||
} | ||
else { | ||
return []; | ||
} | ||
}); | ||
``` | ||
Inspecting the contents of `errors` shows: | ||
_.splitAt([1,2,3,4,5], -1000); | ||
//=> [[],[1,2,3,4,5]] | ||
```javascript | ||
["Element @2 is bad", "Element @4 is bad"] | ||
``` | ||
_.splitAt([], 0); | ||
//=> [[],[]] | ||
The `_.mapcat` function is equivalent to `_.cat.apply(array, _.map(array,fun))`. | ||
-------------------------------------------------------------------------------- | ||
#### takeSkipping | ||
#### reductions | ||
The `_.takeSkipping` function takes an array and a number and returns a new array containing every nth element in the original array: | ||
The `_.reductions` function is similar to Underscore's builtin `_.reduce` function except that it returns an array of every intermediate value in the folding operation: | ||
_.takeSkipping(_.range(10), 2); | ||
//=> [0,2,4,6,8] | ||
```javascript | ||
_.reductions([1,2,3,4,5], function(agg, n) { | ||
return agg + n; | ||
}, 0); | ||
The `_.takeSkipping` function is safe against numbers larger or smaller than the array size: | ||
//=> [1,3,6,10,15] | ||
``` | ||
_.takeSkipping(_.range(10), 100000); | ||
//=> [0] | ||
The last element in the array returned from `_.reductions` is the answer that you would get if you had just chosen to use `_.reduce`. | ||
_.takeSkipping(_.range(10), -100); | ||
//=> [] | ||
-------------------------------------------------------------------------------- | ||
#### reductions | ||
#### repeat | ||
The `_.reductions` function is similar to lodash's builtin `_.reduce` function except that it returns an array of every intermediate value in the folding operation: | ||
Signature: `_.repeat(t:Integer, value:Any)` | ||
_.reductions([1,2,3,4,5], function(agg, n) { | ||
return agg + n; | ||
}, 0); | ||
The `_.repeat` function takes an integer value used to build an array of that size containing the value given: | ||
//=> [1,3,6,10,15] | ||
```javascript | ||
_.repeat(5, 'a'); | ||
//=> ['a','a','a','a','a'] | ||
``` | ||
The last element in the array returned from `_.reductions` is the answer that you would get if you had just chosen to use `_.reduce`. | ||
-------------------------------------------------------------------------------- | ||
#### keepIndexed | ||
#### splitAt | ||
The `_.keepIndexed` function takes an array and a function and returns a new array filled with the *non-null* return results of the given function on the elements or keys in the given array: | ||
The `_.splitAt` function takes an array and a numeric index and returns a new array with two embedded arrays representing a split of the original array at the index provided: | ||
_.keepIndexed([1,2,3], function(k) { | ||
return i === 1 || i === 2; | ||
}); | ||
```javascript | ||
_.splitAt([1,2,3,4,5], 2); | ||
//=> [[1,2],[3,4,5]] | ||
//=> [false, true, true] | ||
_.splitAt([1,2,3,4,5], 0); | ||
//=> [[],[1,2,3,4,5]] | ||
``` | ||
If you return either `null` or `undefined` then the result is dropped from the resulting array: | ||
The operation of `_.splitAt` is safe if the index provided is outside the range of legal indices: | ||
_.keepIndexed(['a','b','c'], function(k, v) { | ||
if (k === 1) return v; | ||
}); | ||
```javascript | ||
_.splitAt([1,2,3,4,5], 20000); | ||
//=> [[1,2,3,4,5],[]] | ||
//=> ['b'] | ||
_.splitAt([1,2,3,4,5], -1000); | ||
//=> [[],[1,2,3,4,5]] | ||
#### iterateUntil | ||
_.splitAt([], 0); | ||
//=> [[],[]] | ||
``` | ||
The `_.iterateUntil` function takes a function used as a result generator, a function used as a stop-check and a seed value and returns an array of each generated result. The operation of `_.iterateUntil` is such that the result generator is passed the seed to start and each subsequent result which will continue **until** a result fails the check function (i.e. returns falsey). An example is best: | ||
-------------------------------------------------------------------------------- | ||
var dec = function(n) { return n - 1; }; | ||
var isPos = function(n) { return n > 0; }; | ||
#### takeSkipping | ||
The `dec` result generator takes a number and decrements it by one. The `isPos` predicate takes a number and returns `true` if it's positive. Using these two functions you can build an array of every number from `6` to `0`, inclusive: | ||
The `_.takeSkipping` function takes an array and a number and returns a new array containing every nth element in the original array: | ||
_.iterateUntil(dec, isPos, 6); | ||
//=> [5,4,3,2,1] | ||
```javascript | ||
_.takeSkipping(_.range(10), 2); | ||
//=> [0,2,4,6,8] | ||
``` | ||
That is, the array only contains every number from `5` down to `1` because when the result of `dec` got to `0` the `isPos` check failed (i.e. went falsey) thus terminating the execution. | ||
The `_.takeSkipping` function is safe against numbers larger or smaller than the array size: | ||
```javascript | ||
_.takeSkipping(_.range(10), 100000); | ||
//=> [0] | ||
_.takeSkipping(_.range(10), -100); | ||
//=> [] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### weave | ||
The `_.weave` function works similarly to `_.interpose` (shown above) except that it accepts an array used as the interposition values. In other words, `_.weave` takes two arrays and returns a new array with the original elements woven together. An example would help: | ||
```javascript | ||
_.weave(['a','b','c'], [1,2,3]); | ||
//=> ['a',1,'b',2,'c',3] | ||
``` | ||
The array returned from `_.weave` will be as long as the longest array given with the woven entries stopping according to the shortest array: | ||
```javascript | ||
_.weave(['a','b','c'], [1]); | ||
//=> ['a',1,'b','c'] | ||
``` | ||
The `_.interleave` function is an alias for `_.weave`. | ||
-------------------------------------------------------------------------------- |
@@ -5,67 +5,162 @@ ### array.selectors | ||
#### second | ||
-------------------------------------------------------------------------------- | ||
The `_.second` function is a convenience for the equivalent `array[1]`: | ||
#### best | ||
_.second(['a','b']); | ||
//=> 'b' | ||
**Signature:** `_.best(array:Array, fun:Function)` | ||
_.map([['a','b'], _.range(10,20)], _.second); | ||
//=> ['b',11] | ||
Returns the "best" value in an array based on the result of a given function. | ||
You can also pass an optional number to the `_.second` function to take a number of elements from an array starting with the second element and ending at the given index: | ||
```javascript | ||
_.best([1, 2, 3, 4, 5], function(x, y) { | ||
return x > y; | ||
}); | ||
//=> 5 | ||
``` | ||
_.second(_.range(10), 5) | ||
//=> [1, 2, 3, 4] | ||
-------------------------------------------------------------------------------- | ||
#### third | ||
#### dropWhile | ||
The `_.third` function is a convenience for the equivalent `array[2]`: | ||
**Signature:** `_.dropWhile(array:Array, pred:Function)` | ||
_.third(['a','b','c']); | ||
//=> 'c' | ||
Drops elements for which the given function returns a truthy value. | ||
_.map([['a','b','c'], _.range(10,20)], _.third); | ||
//=> ['c',12] | ||
```javascript | ||
_.dropWhile([-2,-1,0,1,2], isNeg); | ||
//=> [0,1,2] | ||
``` | ||
You can also pass an optional number to the `_.third` function to take a number of elements from an array starting with the third element and ending at the given index: | ||
-------------------------------------------------------------------------------- | ||
_.third(_.range(10), 5) | ||
//=> [2, 3, 4] | ||
#### keep | ||
**Signature:** `_.keep(array:Array, fun:Function)` | ||
Returns an array of existy results of a function over a source array. | ||
```javascript | ||
_.keep([1, 2, 3, 4, 5], function(val) { | ||
if (val % 3 === 0) { | ||
return val; | ||
} | ||
}); | ||
// => [3] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### nth | ||
The `_.nth` function is a convenience for the equivalent `array[n]`: | ||
**Signature:** `_.nth(array:Array, index:Number[, guard:Any])` | ||
_.nth(['a','b','c'], 2); | ||
//=> 'c' | ||
The `_.nth` function is a convenience for the equivalent `array[n]`. The | ||
optional `guard` value allows `_.nth` to work correctly as a callback for | ||
`_.map`. | ||
```javascript | ||
_.nth(['a','b','c'], 2); | ||
//=> 'c' | ||
``` | ||
If given an index out of bounds then `_.nth` will return `undefined`: | ||
_.nth(['a','b','c'], 2000); | ||
//=> undefined | ||
```javascript | ||
_.nth(['a','b','c'], 2000); | ||
//=> undefined | ||
``` | ||
The `_.nth` function can also be used in conjunction with `_.map` and `_.compact` like so: | ||
var b = [['a'],['b'],[]]; | ||
```javascript | ||
var b = [['a'],['b'],[]]; | ||
_.compact(_.map(b, function(e) { return _.nth(e,0) })); | ||
//=> ['a','b'] | ||
_.compact(_.map(b, function(e) { return _.nth(e,0) })); | ||
//=> ['a','b'] | ||
``` | ||
If wrapping a function around `_.nth` is too tedious or you'd like to partially apply the index then lodash-contrib offers any of `_.flip2`, `_.fix` or `rcurry2` to solve this. | ||
If wrapping a function around `_.nth` is too tedious or you'd like to partially apply the index then Underscore-contrib offers any of `_.flip2`, `_.fix` or `rcurry2` to solve this. | ||
-------------------------------------------------------------------------------- | ||
#### partitionBy | ||
**Signature:** `_.keep(array:Array, fun:Function)` | ||
Takes an array and partitions it into sub-arrays as the given predicate changes | ||
truth sense. | ||
```javascript | ||
_.partitionBy([1,2,2,3,1,1,5], _.isEven); | ||
// => [[1],[2,2],[3,1,1,5]] | ||
_.partitionBy([1,2,2,3,1,1,5], _.identity); | ||
// => [[1],[2,2],[3],[1,1],[5]] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### second | ||
**Signature:** `_.second(array:Array, index:Number[, guard:Any])` | ||
The `_.second` function is a convenience for the equivalent `array[1]`. The | ||
optional `guard` value allows `_.second` to work correctly as a callback for | ||
`_.map`. | ||
```javascript | ||
_.second(['a','b']); | ||
//=> 'b' | ||
_.map([['a','b'], _.range(10,20)], _.second); | ||
//=> ['b',11] | ||
``` | ||
You can also pass an optional number to the `_.second` function to take a number of elements from an array starting with the second element and ending at the given index: | ||
```javascript | ||
_.second(_.range(10), 5) | ||
//=> [1, 2, 3, 4] | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### takeWhile | ||
**Signature:** `_.takeWhile(array:Array, pred:Function)` | ||
The `_.takeWhile` function takes an array and a function and returns a new array containing the first n elements in the original array for which the given function returns a truthy value: | ||
var isNeg = function(n) { return n < 0; }; | ||
```javascript | ||
var isNeg = function(n) { return n < 0; }; | ||
_.takeWhile([-2,-1,0,1,2], isNeg); | ||
//=> [-2,-1] | ||
_.takeWhile([-2,-1,0,1,2], isNeg); | ||
//=> [-2,-1] | ||
``` | ||
#### dropWhile | ||
-------------------------------------------------------------------------------- | ||
The `_.dropWhile` function works similarly except that it *drops* elements from the original array for which the given function returns a truthy value: | ||
#### third | ||
_.dropWhile([-2,-1,0,1,2], isNeg); | ||
//=> [0,1,2] | ||
**Signature:** `_.third(array:Array, index:Number[, guard:Any])` | ||
The `_.third` function is a convenience for the equivalent `array[2]`. The | ||
optional `guard` value allows `_.third` to work correctly as a callback for | ||
`_.map`. | ||
```javascript | ||
_.third(['a','b','c']); | ||
//=> 'c' | ||
_.map([['a','b','c'], _.range(10,20)], _.third); | ||
//=> ['c',12] | ||
``` | ||
You can also pass an optional number to the `_.third` function to take a number of elements from an array starting with the third element and ending at the given index: | ||
```javascript | ||
_.third(_.range(10), 5) | ||
//=> [2, 3, 4] | ||
``` | ||
-------------------------------------------------------------------------------- |
@@ -163,3 +163,3 @@ ### object.selectors | ||
_.omitWhen(obj, function (country) { return country == "England" }); | ||
_.pickWhen(obj, function (country) { return country == "England" }); | ||
// => { shakespeare: "England" } | ||
@@ -166,0 +166,0 @@ ``` |
@@ -5,2 +5,4 @@ ### util.strings | ||
-------------------------------------------------------------------------------- | ||
#### camelCase | ||
@@ -17,2 +19,4 @@ | ||
-------------------------------------------------------------------------------- | ||
#### explode | ||
@@ -29,2 +33,18 @@ | ||
-------------------------------------------------------------------------------- | ||
#### fromQuery | ||
**Signature:** `_.fromQuery(str:String)` | ||
Takes a URL query string and converts it into an equivalent JavaScript object. | ||
Opposite of [toQuery](#toquery) | ||
```javascript | ||
_.fromQuery("forms%5Bperfect%5D=circle&forms%5Bimperfect%5D=square"); | ||
// => { forms: { perfect: "circle", imperfect: "square" } } | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### implode | ||
@@ -41,2 +61,4 @@ | ||
-------------------------------------------------------------------------------- | ||
#### strContains | ||
@@ -53,2 +75,4 @@ | ||
-------------------------------------------------------------------------------- | ||
#### toDash | ||
@@ -63,2 +87,18 @@ | ||
// => "this-is-sparta" | ||
``` | ||
``` | ||
-------------------------------------------------------------------------------- | ||
#### toQuery | ||
**Signature:** `_.toQuery(obj:Object)` | ||
Takes an object and converts it into an equivalent URL query string. Opposite | ||
of [fromQuery](#fromquery). | ||
```javascript | ||
_.toQuery({ forms: { perfect: "circle", imperfect: "square" } }); | ||
// => "forms%5Bperfect%5D=circle&forms%5Bimperfect%5D=square" | ||
``` | ||
-------------------------------------------------------------------------------- |
@@ -9,1 +9,3 @@ ### util.trampolines | ||
trampoline: function(fun /*, args */) { | ||
-------------------------------------------------------------------------------- |
@@ -25,11 +25,14 @@ # lodash-contrib | ||
#### In the Browser | ||
First, you’ll need lodash. Then you can grab the relevant lodash-contrib libraries and simply add | ||
something | ||
like the following to your pages: | ||
the following to your pages: | ||
```html | ||
<script type="text/javascript" src="lodash.js"></script> | ||
<script type="text/javascript" src="lodash.object.builders.js"></script> | ||
``` | ||
At the moment there are no cross-contrib dependencies (i.e. each library can stand by itself), but that may | ||
change in the future. | ||
At the moment there are no cross-contrib dependencies (i.e. each sub-library | ||
can stand by itself), but that may change in the future. | ||
@@ -39,2 +42,3 @@ ### License | ||
lodash-contrib is open sourced under the [MIT license](https://github.com/Empeeric/lodash-contrib/blob/master/LICENSE). | ||
## Sub-libraries | ||
@@ -41,0 +45,0 @@ |
@@ -71,3 +71,3 @@ module.exports = function(grunt) { | ||
files: { | ||
'index.html': 'docs/*.md' | ||
'index.html': ['docs/*.md', 'CHANGELOG.md'] | ||
} | ||
@@ -74,0 +74,0 @@ } |
{ | ||
"name": "lodash-contrib", | ||
"description": "The brass buckles on lodash's utility belt", | ||
"version": "241.4.4", | ||
"version": "241.4.5", | ||
"main": "index.js", | ||
@@ -28,11 +28,8 @@ "dependencies": { | ||
"contributors": [ | ||
{ | ||
"name": "Refael Ackermann", | ||
"email": "refael@empeeric.com", | ||
"url": "http://www.empeeric.com/" | ||
} | ||
"Refael Ackermann <refael@empeeric.com> (http://www.empeeric.com)", | ||
"John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)" | ||
], | ||
"scripts": { | ||
"test": "node ./node_modules/grunt-cli/bin/grunt test" | ||
"test": "grunt test" | ||
} | ||
} |
@@ -65,3 +65,3 @@ $(document).ready(function() { | ||
deepEqual(_.keep(a, eveny), [0,2,4,6,8], 'should keep only even numbers in a range tagged with null fails'); | ||
deepEqual(_.keep(a, _.isEven), [true, false, true, false, true, false, true, false, true, false], 'should keep all truthy values cooresponding to a predicate over a range'); | ||
deepEqual(_.keep(a, _.isEven), [true, false, true, false, true, false, true, false, true, false], 'should keep all existy values corresponding to a predicate over a range'); | ||
}); | ||
@@ -68,0 +68,0 @@ |
@@ -46,4 +46,37 @@ $(document).ready(function() { | ||
equal(notOdd(3), false, 'should return a function that is the opposite of the function given'); | ||
var obj = { | ||
num: 1, | ||
numIsPositive: function () { return this.num > 0; } | ||
}; | ||
obj.numIsNotPositive = _.complement(obj.numIsPositive); | ||
equal(obj.numIsNotPositive(), false, 'should function as a method combinator'); | ||
}); | ||
test('splat', function() { | ||
var sumArgs = function () { | ||
return _.reduce(arguments, function (a, b) { return a + b; }, 0); | ||
}; | ||
var sumArray = _.splat(sumArgs); | ||
equal(sumArray([1, 2, 3]), 6, 'should return a function that takes array elements as the arguments for the original function'); | ||
var obj = { | ||
a: 1, | ||
b: 2, | ||
getPropsByName: function () { | ||
var props = []; | ||
for (var i = 0; i < arguments.length; i++) { | ||
props.push(this[arguments[i]]); | ||
} | ||
return props; | ||
} | ||
}; | ||
obj.getPropsByNameArray = _.splat(obj.getPropsByName); | ||
deepEqual(obj.getPropsByNameArray(['a', 'b']), [1, 2], 'should function as a method combinator'); | ||
}); | ||
test("unsplat", function() { | ||
@@ -113,2 +146,11 @@ var echo = _.unsplat(function (args) { return args; }), | ||
equal(_.flip2(div)(10,2), 0.2, 'should return a function that flips the first two args to a function'); | ||
var obj = { | ||
num: 5, | ||
addToNum: function (a, b) { return [a + this.num, b + this.num]; } | ||
}; | ||
obj.reversedAddToNum = _.flip2(obj.addToNum); | ||
deepEqual(obj.reversedAddToNum(1, 2), [7, 6], 'should function as a method combinator.'); | ||
}); | ||
@@ -120,2 +162,11 @@ | ||
deepEqual(_.flip(echo)(1, 2, 3, 4), [4, 3, 2, 1], 'should return a function that flips the first three or more args to a function'); | ||
var obj = { | ||
num: 5, | ||
addToNum: function (a, b) { return [a + this.num, b + this.num]; } | ||
}; | ||
obj.reversedAddToNum = _.flip(obj.addToNum); | ||
deepEqual(obj.reversedAddToNum(1, 2), [7, 6], 'should function as a method combinator.'); | ||
}); | ||
@@ -131,2 +182,12 @@ | ||
equal(_.reduce(b, safeMult), 30, 'should fill in defaults for undefined'); | ||
var obj = { | ||
a: 1, | ||
fallback: "fallback value", | ||
getPropByName: function (name) { return this[name]; } | ||
}; | ||
obj.getPropByNameOrDefault = _.fnull(obj.getPropByName, "fallback"); | ||
equal(obj.getPropByNameOrDefault(), "fallback value", 'should function as a method combinator.'); | ||
}); | ||
@@ -138,2 +199,12 @@ | ||
deepEqual(run('42', 10), [12, 42, 108], 'should return a function that returns an array of the originally supplied functions called'); | ||
var obj = { | ||
name: "Elizabeth 1", | ||
firstChar: function () { return this.name[0]; }, | ||
lastChar: function () { return this.name[this.name.length - 1]; } | ||
}; | ||
obj.firstAndLastChars = _.juxt(obj.firstChar, obj.lastChar); | ||
deepEqual(obj.firstAndLastChars(), ['E', '1'], 'should function as a method combinator.'); | ||
}); | ||
@@ -140,0 +211,0 @@ |
@@ -0,0 +0,0 @@ var _ = require('lodash'); |
@@ -11,4 +11,18 @@ | ||
test('fromQuery', function() { | ||
var query = 'foo%26bar=baz&test=total+utter+success'; | ||
ok(_.isEqual(_.fromQuery(query), {'foo&bar': 'baz', 'test': 'total utter success'}), 'can convert a query string to a hash'); | ||
var query = 'foo%5Bbar%5D%5Bbaz%5D%5Bblargl%5D=blah&foo%5Bbar%5D%5Bbaz%5D%5Bblargr%5D=woop&blar=bluh&abc[]=123&abc[]=234'; | ||
ok(_.isEqual(_.fromQuery(query), { | ||
'foo': { | ||
'bar': { | ||
'baz': { | ||
'blargl': 'blah', | ||
'blargr': 'woop' | ||
} | ||
} | ||
}, | ||
'blar': 'bluh', | ||
'abc': [ | ||
'123', | ||
'234' | ||
] | ||
}), 'can convert a query string to a hash'); | ||
}); | ||
@@ -30,4 +44,5 @@ | ||
test('toQuery', function() { | ||
var obj = {'foo&bar': 'baz', 'test': 'total success'}; | ||
equal(_.toQuery(obj), 'foo%26bar=baz&test=total%20success', 'can convert a hash to a query string'); | ||
var obj = {'foo&bar': 'baz', 'test': 'total success', 'nested': {'works': 'too'}, 'isn\'t': ['that', 'cool?']}; | ||
equal(_.toQuery(obj), 'foo%26bar=baz&test=total+success&nested%5Bworks%5D=too&isn\'t%5B%5D=that&isn\'t%5B%5D=cool%3F', 'can convert a hash to a query string'); | ||
equal(_.toQuery(obj), jQuery.param(obj), 'query serialization matchs jQuery.param()'); | ||
}); | ||
@@ -34,0 +49,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1517169
92
29000