mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-08 02:17:48 +00:00
Move _.pluck and _.invoke back to the "Collections" category and optimize _.sortedIndex when a callback is passed.
Former-commit-id: d16763e7d35660d8ba9ea976c8b2a4dc20f1211f
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
/** Used to minify variables embedded in compiled strings */
|
/** Used to minify variables embedded in compiled strings */
|
||||||
var compiledVars = [
|
var compiledVars = [
|
||||||
'accumulator',
|
'accumulator',
|
||||||
|
'args',
|
||||||
'arrayClass',
|
'arrayClass',
|
||||||
'callback',
|
'callback',
|
||||||
'className',
|
'className',
|
||||||
@@ -18,14 +19,17 @@
|
|||||||
'hasOwnProperty',
|
'hasOwnProperty',
|
||||||
'identity',
|
'identity',
|
||||||
'index',
|
'index',
|
||||||
|
'isFunc',
|
||||||
'iteratorBind',
|
'iteratorBind',
|
||||||
'length',
|
'length',
|
||||||
|
'methodName',
|
||||||
|
'noaccum',
|
||||||
'object',
|
'object',
|
||||||
'objectTypes',
|
'objectTypes',
|
||||||
'noaccum',
|
|
||||||
'property',
|
'property',
|
||||||
'result',
|
'result',
|
||||||
'skipProto',
|
'skipProto',
|
||||||
|
'slice',
|
||||||
'source',
|
'source',
|
||||||
'sourceIndex',
|
'sourceIndex',
|
||||||
'stringClass',
|
'stringClass',
|
||||||
|
|||||||
169
lodash.js
169
lodash.js
@@ -339,6 +339,20 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Reusable iterator options for `invoke`, `map`, and `pluck` */
|
||||||
|
var mapIteratorOptions = {
|
||||||
|
'init': '',
|
||||||
|
'exit': 'if (!collection) return []',
|
||||||
|
'beforeLoop': {
|
||||||
|
'array': 'result = Array(length)',
|
||||||
|
'object': 'result = []'
|
||||||
|
},
|
||||||
|
'inLoop': {
|
||||||
|
'array': 'result[index] = callback(collection[index], index, collection)',
|
||||||
|
'object': 'result.push(callback(collection[index], index, collection))'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -437,13 +451,13 @@
|
|||||||
// create the function factory
|
// create the function factory
|
||||||
var factory = Function(
|
var factory = Function(
|
||||||
'arrayClass, funcClass, hasOwnProperty, identity, iteratorBind, objectTypes, ' +
|
'arrayClass, funcClass, hasOwnProperty, identity, iteratorBind, objectTypes, ' +
|
||||||
'stringClass, toString, undefined',
|
'slice, stringClass, toString, undefined',
|
||||||
'"use strict"; return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
'"use strict"; return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
||||||
);
|
);
|
||||||
// return the compiled function
|
// return the compiled function
|
||||||
return factory(
|
return factory(
|
||||||
arrayClass, funcClass, hasOwnProperty, identity, iteratorBind, objectTypes,
|
arrayClass, funcClass, hasOwnProperty, identity, iteratorBind, objectTypes,
|
||||||
stringClass, toString
|
slice, stringClass, toString
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,7 +693,40 @@
|
|||||||
var forEach = createIterator(baseIteratorOptions, forEachIteratorOptions);
|
var forEach = createIterator(baseIteratorOptions, forEachIteratorOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produces a new array of values by mapping each value in the `collection`
|
* Invokes the method named by `methodName` on each element in the `collection`.
|
||||||
|
* Additional arguments will be passed to each invoked method. If `methodName`
|
||||||
|
* is a function it will be invoked for, and `this` bound to, each element
|
||||||
|
* in the `collection`.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @category Collections
|
||||||
|
* @param {Array|Object} collection The collection to iterate over.
|
||||||
|
* @param {Function|String} methodName The name of the method to invoke or
|
||||||
|
* the function invoked per iteration.
|
||||||
|
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
|
||||||
|
* @returns {Array} Returns a new array of values returned from each invoked method.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
|
||||||
|
* // => [[1, 5, 7], [1, 2, 3]]
|
||||||
|
*
|
||||||
|
* _.invoke([123, 456], String.prototype.split, '');
|
||||||
|
* // => [['1', '2', '3'], ['4', '5', '6']]
|
||||||
|
*/
|
||||||
|
var invoke = createIterator(mapIteratorOptions, {
|
||||||
|
'args': 'collection, methodName',
|
||||||
|
'top':
|
||||||
|
'var args = slice.call(arguments, 2),\n' +
|
||||||
|
' isFunc = typeof methodName == \'function\'',
|
||||||
|
'inLoop': {
|
||||||
|
'array': 'result[index] = (isFunc ? methodName : collection[index][methodName]).apply(collection[index], args)',
|
||||||
|
'object': 'result.push((isFunc ? methodName : collection[index][methodName]).apply(collection[index], args))'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produces a new array of values by mapping each element in the `collection`
|
||||||
* through a transformation `callback`. The `callback` is bound to `thisArg`
|
* through a transformation `callback`. The `callback` is bound to `thisArg`
|
||||||
* and invoked with 3 arguments; for arrays they are (value, index, array)
|
* and invoked with 3 arguments; for arrays they are (value, index, array)
|
||||||
* and for objects they are (value, key, object).
|
* and for objects they are (value, key, object).
|
||||||
@@ -700,16 +747,34 @@
|
|||||||
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
|
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
|
||||||
* // => [3, 6, 9] (order is not guaranteed)
|
* // => [3, 6, 9] (order is not guaranteed)
|
||||||
*/
|
*/
|
||||||
var map = createIterator(baseIteratorOptions, {
|
var map = createIterator(baseIteratorOptions, mapIteratorOptions);
|
||||||
'init': '',
|
|
||||||
'exit': 'if (!collection) return []',
|
/**
|
||||||
'beforeLoop': {
|
* Retrieves the value of a specified property from all elements in
|
||||||
'array': 'result = Array(length)',
|
* the `collection`.
|
||||||
'object': 'result = []'
|
*
|
||||||
},
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @category Collections
|
||||||
|
* @param {Array|Object} collection The collection to iterate over.
|
||||||
|
* @param {String} property The property to pluck.
|
||||||
|
* @returns {Array} Returns a new array of property values.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var stooges = [
|
||||||
|
* { 'name': 'moe', 'age': 40 },
|
||||||
|
* { 'name': 'larry', 'age': 50 },
|
||||||
|
* { 'name': 'curly', 'age': 60 }
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* _.pluck(stooges, 'name');
|
||||||
|
* // => ['moe', 'larry', 'curly']
|
||||||
|
*/
|
||||||
|
var pluck = createIterator(mapIteratorOptions, {
|
||||||
|
'args': 'collection, property',
|
||||||
'inLoop': {
|
'inLoop': {
|
||||||
'array': 'result[index] = callback(collection[index], index, collection)',
|
'array': 'result[index] = collection[index][property]',
|
||||||
'object': 'result.push(callback(collection[index], index, collection))'
|
'object': 'result.push(collection[index][property])'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1159,44 +1224,6 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes the method named by `methodName` on each element of `array`.
|
|
||||||
* Additional arguments will be passed to each invoked method. If `methodName`
|
|
||||||
* is a function it will be invoked for, and `this` bound to, each element
|
|
||||||
* of `array`.
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @memberOf _
|
|
||||||
* @category Arrays
|
|
||||||
* @param {Array} array The array to iterate over.
|
|
||||||
* @param {Function|String} methodName The name of the method to invoke or
|
|
||||||
* the function invoked per iteration.
|
|
||||||
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
|
|
||||||
* @returns {Array} Returns a new array of values returned from each invoked method.
|
|
||||||
* @example
|
|
||||||
*
|
|
||||||
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
|
|
||||||
* // => [[1, 5, 7], [1, 2, 3]]
|
|
||||||
*
|
|
||||||
* _.invoke([123, 456], String.prototype.split, '');
|
|
||||||
* // => [['1', '2', '3'], ['4', '5', '6']]
|
|
||||||
*/
|
|
||||||
function invoke(array, methodName) {
|
|
||||||
var result = [];
|
|
||||||
if (!array) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
var args = slice.call(arguments, 2),
|
|
||||||
index = -1,
|
|
||||||
length = array.length,
|
|
||||||
isFunc = typeof methodName == 'function';
|
|
||||||
|
|
||||||
while (++index < length) {
|
|
||||||
result[index] = (isFunc ? methodName : array[index][methodName]).apply(array[index], args);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the last value of the `array`. Pass `n` to return the lasy `n` values
|
* Gets the last value of the `array`. Pass `n` to return the lasy `n` values
|
||||||
* of the `array`.
|
* of the `array`.
|
||||||
@@ -1363,40 +1390,6 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the value of a specified property from all elements in `array`.
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @memberOf _
|
|
||||||
* @category Arrays
|
|
||||||
* @param {Array} array The array to iterate over.
|
|
||||||
* @param {String} property The property to pluck.
|
|
||||||
* @returns {Array} Returns a new array of property values.
|
|
||||||
* @example
|
|
||||||
*
|
|
||||||
* var stooges = [
|
|
||||||
* { 'name': 'moe', 'age': 40 },
|
|
||||||
* { 'name': 'larry', 'age': 50 },
|
|
||||||
* { 'name': 'curly', 'age': 60 }
|
|
||||||
* ];
|
|
||||||
*
|
|
||||||
* _.pluck(stooges, 'name');
|
|
||||||
* // => ['moe', 'larry', 'curly']
|
|
||||||
*/
|
|
||||||
function pluck(array, property) {
|
|
||||||
if (!array) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
var index = -1,
|
|
||||||
length = array.length,
|
|
||||||
result = Array(length);
|
|
||||||
|
|
||||||
while (++index < length) {
|
|
||||||
result[index] = array[index][property];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an array of numbers (positive and/or negative) progressing from
|
* Creates an array of numbers (positive and/or negative) progressing from
|
||||||
* `start` up to but not including `stop`. This method is a port of Python's
|
* `start` up to but not including `stop`. This method is a port of Python's
|
||||||
@@ -1608,10 +1601,14 @@
|
|||||||
high = array.length;
|
high = array.length;
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
value = callback.call(thisArg, value);
|
if (thisArg) {
|
||||||
|
var fn = callback;
|
||||||
|
callback = function(value) { return fn.call(thisArg, value); };
|
||||||
|
}
|
||||||
|
value = callback(value);
|
||||||
while (low < high) {
|
while (low < high) {
|
||||||
mid = (low + high) >>> 1;
|
mid = (low + high) >>> 1;
|
||||||
callback.call(thisArg, array[mid]) < value ? low = mid + 1 : high = mid;
|
callback(array[mid]) < value ? low = mid + 1 : high = mid;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (low < high) {
|
while (low < high) {
|
||||||
|
|||||||
26
test/test.js
26
test/test.js
@@ -378,6 +378,17 @@
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
QUnit.module('lodash.invoke');
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
test('should work with an object for `collection`', function() {
|
||||||
|
var object = { 'a': 1, 'b': 2, 'c': 3 };
|
||||||
|
deepEqual(_.invoke(object, 'toFixed', 1), ['1.0', '2.0', '3.0']);
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
QUnit.module('lodash.isEmpty');
|
QUnit.module('lodash.isEmpty');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
@@ -520,6 +531,17 @@
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
QUnit.module('lodash.pluck');
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
test('should work with an object for `collection`', function() {
|
||||||
|
var object = { 'a': [1], 'b': [1, 2], 'c': [1, 2, 3] };
|
||||||
|
deepEqual(_.pluck(object, 'length'), [1, 2, 3]);
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
QUnit.module('lodash.reduceRight');
|
QUnit.module('lodash.reduceRight');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
@@ -743,12 +765,10 @@
|
|||||||
'indexOf',
|
'indexOf',
|
||||||
'initial',
|
'initial',
|
||||||
'intersection',
|
'intersection',
|
||||||
'invoke',
|
|
||||||
'last',
|
'last',
|
||||||
'lastIndexOf',
|
'lastIndexOf',
|
||||||
'max',
|
'max',
|
||||||
'min',
|
'min',
|
||||||
'pluck',
|
|
||||||
'range',
|
'range',
|
||||||
'rest',
|
'rest',
|
||||||
'shuffle',
|
'shuffle',
|
||||||
@@ -782,7 +802,9 @@
|
|||||||
'filter',
|
'filter',
|
||||||
'find',
|
'find',
|
||||||
'forEach',
|
'forEach',
|
||||||
|
'invoke',
|
||||||
'map',
|
'map',
|
||||||
|
'pluck',
|
||||||
'reduce',
|
'reduce',
|
||||||
'reduceRight',
|
'reduceRight',
|
||||||
'reject',
|
'reject',
|
||||||
|
|||||||
Reference in New Issue
Block a user