Separate _.uniq isSorted logic to a helper

This commit is contained in:
megawac
2014-07-13 16:55:46 -04:00
committed by John-David Dalton
parent 6f937e8958
commit 95ba6bf040
2 changed files with 28 additions and 18 deletions

View File

@@ -2380,17 +2380,35 @@
return high; return high;
} }
/**
* The implementation of `_.uniq` optimized for sorted arrays
*
* @private
* @param {Array} array The array to inspect.
* @returns {Array} Returns the new duplicate-value-free array.
*/
function sortedUniq(array) {
var result = [],
index = -1,
length = array ? array.length : 0;
while (++index < length) {
if (index + 1 > length || array[index] !== array[index + 1]) {
result.push(array[index]);
}
}
return result;
};
/** /**
* The base implementation of `_.uniq` without support for callback shorthands * The base implementation of `_.uniq` without support for callback shorthands
* and `this` binding. * and `this` binding.
* *
* @private * @private
* @param {Array} array The array to inspect. * @param {Array} array The array to inspect.
* @param {boolean} [isSorted=false] Specify the array is sorted.
* @param {Function} [iterator] The function called per iteration. * @param {Function} [iterator] The function called per iteration.
* @returns {Array} Returns the new duplicate-value-free array. * @returns {Array} Returns the new duplicate-value-free array.
*/ */
function baseUniq(array, isSorted, iterator) { function baseUniq(array, iterator) {
var length = array ? array.length : 0; var length = array ? array.length : 0;
if (!length) { if (!length) {
return []; return [];
@@ -2402,12 +2420,11 @@
isCommon = prereq && !isLarge, isCommon = prereq && !isLarge,
result = []; result = [];
isSorted = prereq && isSorted;
if (isLarge) { if (isLarge) {
var seen = createCache(); var seen = createCache();
indexOf = cacheIndexOf; indexOf = cacheIndexOf;
} else { } else {
seen = (iterator && !isSorted) ? [] : result; seen = iterator ? [] : result;
} }
outer: outer:
while (++index < length) { while (++index < length) {
@@ -2426,12 +2443,6 @@
} }
result.push(value); result.push(value);
} }
else if (isSorted) {
if (!index || seen !== computed) {
seen = computed;
result.push(value);
}
}
else if (indexOf(seen, computed) < 0) { else if (indexOf(seen, computed) < 0) {
if (iterator || isLarge) { if (iterator || isLarge) {
seen.push(computed); seen.push(computed);
@@ -4095,26 +4106,23 @@
* // => [{ 'x': 1 }, { 'x': 2 }] * // => [{ 'x': 1 }, { 'x': 2 }]
*/ */
function uniq(array, isSorted, iterator, thisArg) { function uniq(array, isSorted, iterator, thisArg) {
var length = array ? array.length : 0;
if (!length) {
return [];
}
// juggle arguments // juggle arguments
var type = typeof isSorted; var type = typeof isSorted;
if (type != 'boolean' && isSorted != null) { if (type != 'boolean' && isSorted != null) {
thisArg = iterator; thisArg = iterator;
iterator = isSorted; iterator = isSorted;
isSorted = false;
// enables use as a callback for functions like `_.map` // enables use as a callback for functions like `_.map`
if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === array) { if ((type == 'number' || type == 'string') && thisArg && thisArg[iterator] === array) {
iterator = null; iterator = null;
} }
} else if (isSorted && getIndexOf() == baseIndexOf) {
return sortedUniq(array);
} }
if (iterator != null) { if (iterator != null) {
iterator = getCallback(iterator, thisArg, 3); iterator = getCallback(iterator, thisArg, 3);
} }
return baseUniq(array, isSorted, iterator); return baseUniq(array, iterator);
} }
/** /**

View File

@@ -10683,9 +10683,11 @@
deepEqual(_.uniq(objects), objects); deepEqual(_.uniq(objects), objects);
}); });
test('should work with `isSorted`', 1, function() { test('should work with `isSorted`', 4, function() {
var array = [1, 1, 2, 2, 3];
deepEqual(_.uniq([1, 1, 2, 2, 3], true), [1, 2, 3]); deepEqual(_.uniq([1, 1, 2, 2, 3], true), [1, 2, 3]);
deepEqual(_.uniq(_.range(100), true), _.range(100));
deepEqual(_.uniq(_.times(100, _.constant(undefined))), [undefined]);
deepEqual(_.uniq([1, 2, 3, 3, 3, 3, 3]), [1, 2, 3]);
}); });
test('should work with a callback', 1, function() { test('should work with a callback', 1, function() {