From 421df0dff374d94d11374bc5e9bf048859b6e688 Mon Sep 17 00:00:00 2001 From: Len Smith Date: Mon, 4 May 2015 10:37:19 -0400 Subject: [PATCH] Make `null` sorted right behind `undefined` and `NaN`. --- lodash.src.js | 25 ++++++++++++++++++++----- test/test.js | 19 +++++++++++-------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lodash.src.js b/lodash.src.js index 359275d7a..2d39b359f 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -298,13 +298,22 @@ */ function baseCompareAscending(value, other) { if (value !== other) { - var valIsReflexive = value === value, + var valIsNull = value === null, + valIsUndef = value === undefined, + valIsReflexive = value === value; + + var othIsNull = other === null, + othIsUndef = other === undefined, othIsReflexive = other === other; - if (value > other || !valIsReflexive || (value === undefined && othIsReflexive)) { + if ((value > other && !othIsNull) || !valIsReflexive || + (valIsNull && !othIsUndef && othIsReflexive) || + (valIsUndef && othIsReflexive)) { return 1; } - if (value < other || !othIsReflexive || (other === undefined && valIsReflexive)) { + if ((value < other && !valIsNull) || !othIsReflexive || + (othIsNull && !valIsUndef && valIsReflexive) || + (othIsUndef && valIsReflexive)) { return -1; } } @@ -3037,7 +3046,7 @@ var mid = (low + high) >>> 1, computed = array[mid]; - if (retHighest ? (computed <= value) : (computed < value)) { + if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) { low = mid + 1; } else { high = mid; @@ -3067,17 +3076,23 @@ var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, + valIsNull = value === null, valIsUndef = value === undefined; while (low < high) { var mid = floor((low + high) / 2), computed = iteratee(array[mid]), + isDef = computed !== undefined, isReflexive = computed === computed; if (valIsNaN) { var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); } else if (valIsUndef) { - setLow = isReflexive && (retHighest || computed !== undefined); + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; } else { setLow = retHighest ? (computed <= value) : (computed < value); } diff --git a/test/test.js b/test/test.js index 09a4eb2cb..3802fb859 100644 --- a/test/test.js +++ b/test/test.js @@ -14415,9 +14415,12 @@ deepEqual(actual, [3, 1, 2]); }); - test('should move `undefined` and `NaN` values to the end', 1, function() { - var array = [NaN, undefined, 4, 1, undefined, 3, NaN, 2]; - deepEqual(_.sortBy(array), [1, 2, 3, 4, undefined, undefined, NaN, NaN]); + test('should move `null`, `undefined`, and `NaN` values to the end', 2, function() { + var array = [NaN, undefined, null, 4, null, 1, undefined, 3, NaN, 2]; + deepEqual(_.sortBy(array), [1, 2, 3, 4, null, null, undefined, undefined, NaN, NaN]); + + array = [NaN, undefined, null, 'd', null, 'a', undefined, 'c', NaN, 'b']; + deepEqual(_.sortBy(array), ['a', 'b', 'c', 'd', null, null, undefined, undefined, NaN, NaN]); }); test('should treat number values for `collection` as empty', 1, function() { @@ -14615,16 +14618,16 @@ }); test('`_.' + methodName + '` should align with `_.sortBy`', 8, function() { - var expected = [1, '2', {}, undefined, NaN, NaN]; + var expected = [1, '2', {}, null, undefined, NaN, NaN]; _.each([ - [NaN, 1, '2', {}, NaN, undefined], - ['2', 1, NaN, {}, NaN, undefined] + [NaN, null, 1, '2', {}, NaN, undefined], + ['2', null, 1, NaN, {}, NaN, undefined] ], function(array) { deepEqual(_.sortBy(array), expected); strictEqual(func(expected, 3), 2); - strictEqual(func(expected, undefined), isSortedIndex ? 3 : 4); - strictEqual(func(expected, NaN), isSortedIndex ? 4 : 6); + strictEqual(func(expected, undefined), isSortedIndex ? 4 : 5); + strictEqual(func(expected, NaN), isSortedIndex ? 5 : 7); }); });