Inline more functionality into _.sortBy.

Former-commit-id: 6549e86881b7a93d96854a9ac1b04f0f5a5db0f1
This commit is contained in:
John-David Dalton
2012-06-29 19:07:05 -04:00
parent e973598bff
commit 10bcb37ca5
2 changed files with 44 additions and 54 deletions

View File

@@ -13,6 +13,7 @@
'callback', 'callback',
'className', 'className',
'collection', 'collection',
'compareAscending',
'ctor', 'ctor',
'funcClass', 'funcClass',
'hasOwnProperty', 'hasOwnProperty',
@@ -25,6 +26,7 @@
'noaccum', 'noaccum',
'object', 'object',
'objectTypes', 'objectTypes',
'prop',
'property', 'property',
'result', 'result',
'skipProto', 'skipProto',
@@ -206,6 +208,9 @@
// remove brackets from `_.escape()` in `tokenizeEscape` // remove brackets from `_.escape()` in `tokenizeEscape`
source = source.replace("_['escape'](\"", '_.escape("'); source = source.replace("_['escape'](\"", '_.escape("');
// remove brackets from `result[length].value` in `_.sortBy`
source = source.replace("result[length]['value']", 'result[length].value');
// remove whitespace from string literals // remove whitespace from string literals
source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) { source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) {
// avoids removing the '\n' of the `stringEscapes` object // avoids removing the '\n' of the `stringEscapes` object
@@ -226,7 +231,7 @@
// minify internal properties used by `_.sortBy` // minify internal properties used by `_.sortBy`
(function() { (function() {
var properties = ['criteria', 'value'], var properties = ['criteria', 'value'],
snippets = source.match(/( +)(?:function compareAscending|function sortBy|var toSortable)\b[\s\S]+?\n\1}/g); snippets = source.match(/( +)(?:function compareAscending|var sortBy)\b[\s\S]+?\n\1}/g);
if (!snippets) { if (!snippets) {
return; return;

View File

@@ -286,7 +286,8 @@
/** /**
* Reusable iterator options shared by * Reusable iterator options shared by
* `every`, `filter`, `find`, `forEach`, `forIn`, `forOwn`, `map`, `reject`, and `some`. * `every`, `filter`, `find`, `forEach`, `forIn`, `forOwn`, `groupBy`, `map`,
* `reject`, `some`, and `sortBy`.
*/ */
var baseIteratorOptions = { var baseIteratorOptions = {
'args': 'collection, callback, thisArg', 'args': 'collection, callback, thisArg',
@@ -339,7 +340,7 @@
} }
}; };
/** Reusable iterator options for `invoke`, `map`, and `pluck` */ /** Reusable iterator options for `invoke`, `map`, `pluck`, and `sortBy` */
var mapIteratorOptions = { var mapIteratorOptions = {
'init': '', 'init': '',
'exit': 'if (!collection) return []', 'exit': 'if (!collection) return []',
@@ -450,20 +451,20 @@
} }
// create the function factory // create the function factory
var factory = Function( var factory = Function(
'arrayClass, funcClass, hasOwnProperty, identity, iteratorBind, objectTypes, ' + 'arrayClass, compareAscending, funcClass, hasOwnProperty, identity, ' +
'slice, stringClass, toString', 'iteratorBind, objectTypes, slice, stringClass, toString',
'"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, compareAscending, funcClass, hasOwnProperty, identity,
slice, stringClass, toString iteratorBind, objectTypes, slice, stringClass, toString
); );
} }
/** /**
* Used by `sortBy()` to compare values of the array returned by `toSortable()`, * Used by `sortBy()` to compare transformed values of `collection`, sorting
* sorting them in ascending order. * them in ascending order.
* *
* @private * @private
* @param {Object} a The object to compare to `b`. * @param {Object} a The object to compare to `b`.
@@ -599,35 +600,6 @@
return token + index; return token + index;
} }
/**
* Converts `collection` to an array of objects by running each element through
* a transformation `callback`. Each object has a `criteria` property containing
* the transformed value to be sorted and a `value` property containing the
* original unmodified value. The `callback` is invoked with 3 arguments;
* for arrays they are (value, index, array) and for objects they are
* (value, key, object).
*
* @private
* @param {Array|Object} collection The collection to convert.
* @param {Function} callback The function called per iteration.
* @returns {Array} Returns a new array of objects to sort.
*/
var toSortable = createIterator(mapIteratorOptions, {
'args': 'collection, callback',
'inLoop': {
'array':
'result[index] = {\n' +
' criteria: callback(collection[index], index, collection),\n' +
' value: collection[index]\n' +
'}',
'object':
'result.push({\n' +
' criteria: callback(collection[index], index, collection),\n' +
' value: collection[index]\n' +
'})'
}
});
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
@@ -1007,7 +979,7 @@
/** /**
* Produces a new sorted array, ranked in ascending order by the results of * Produces a new sorted array, sorted in ascending order by the results of
* running each element of `collection` through a transformation `callback`. * running each element of `collection` through a transformation `callback`.
* The `callback` is bound to `thisArg` and invoked with 3 arguments; * The `callback` is bound to `thisArg` and invoked with 3 arguments;
* for arrays they are (value, index, array) and for objects they are * for arrays they are (value, index, array) and for objects they are
@@ -1033,21 +1005,34 @@
* _.sortBy(['larry', 'brendan', 'moe'], 'length'); * _.sortBy(['larry', 'brendan', 'moe'], 'length');
* // => ['moe', 'larry', 'brendan'] * // => ['moe', 'larry', 'brendan']
*/ */
function sortBy(collection, callback, thisArg) { var sortBy = createIterator(baseIteratorOptions, mapIteratorOptions, {
if (typeof callback == 'string') { 'top':
var prop = callback; 'if (typeof callback == \'string\') {\n' +
callback = function(collection) { return collection[prop]; }; ' var prop = callback;\n' +
} else if (thisArg) { ' callback = function(collection) { return collection[prop] }\n' +
callback = iteratorBind(callback, thisArg); '}\n' +
} 'else if (thisArg) {\n' +
var result = toSortable(collection, callback).sort(compareAscending), ' callback = iteratorBind(callback, thisArg)\n' +
length = result.length; '}',
'inLoop': {
while (length--) { 'array':
result[length] = result[length].value; 'result[index] = {\n' +
} ' criteria: callback(collection[index], index, collection),\n' +
return result; ' value: collection[index]\n' +
} '}',
'object':
'result.push({\n' +
' criteria: callback(collection[index], index, collection),\n' +
' value: collection[index]\n' +
'})'
},
'bottom':
'result.sort(compareAscending);\n' +
'length = result.length;\n' +
'while (length--) {\n' +
' result[length] = result[length].value\n' +
'}'
});
/** /**
* Converts the `collection`, into an array. Useful for converting the * Converts the `collection`, into an array. Useful for converting the