Cleanup flatten methods and add more flattenDepth tests.

This commit is contained in:
John-David Dalton
2016-02-10 00:14:10 -08:00
parent e9edc06aaf
commit ba32bf3b8d
2 changed files with 76 additions and 56 deletions

View File

@@ -2494,14 +2494,12 @@
* *
* @private * @private
* @param {Array} array The array to flatten. * @param {Array} array The array to flatten.
* @param {number} [depth=1] The maximum recursion depth. * @param {number} depth The maximum recursion depth.
* @param {boolean} [isStrict] Restrict flattening to arrays-like objects. * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
* @param {Array} [result=[]] The initial result value. * @param {Array} [result=[]] The initial result value.
* @returns {Array} Returns the new flattened array. * @returns {Array} Returns the new flattened array.
*/ */
function baseFlatten(array, depth, isStrict, result) { function baseFlatten(array, depth, isStrict, result) {
depth = depth === undefined ? 1 : depth;
result || (result = []); result || (result = []);
var index = -1, var index = -1,
@@ -5807,7 +5805,7 @@
} }
/** /**
* Flattens `array` a single level. * Flattens `array` a single level deep.
* *
* @static * @static
* @memberOf _ * @memberOf _
@@ -5816,8 +5814,8 @@
* @returns {Array} Returns the new flattened array. * @returns {Array} Returns the new flattened array.
* @example * @example
* *
* _.flatten([1, 2, [3, [4]]]); * _.flatten([1, [2, [3, [4]], 5]]);
* // => [1, 2, 3, [4]] * // => [1, 2, [3, [4]], 5]
*/ */
function flatten(array) { function flatten(array) {
var length = array ? array.length : 0; var length = array ? array.length : 0;
@@ -5825,16 +5823,16 @@
} }
/** /**
* This method is like `_.flatten` except that it recursively flattens `array`. * Recursively flattens `array`.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Array * @category Array
* @param {Array} array The array to recursively flatten. * @param {Array} array The array to flatten.
* @returns {Array} Returns the new flattened array. * @returns {Array} Returns the new flattened array.
* @example * @example
* *
* _.flattenDeep([1, [2, [3, [[4]]], 5]]); * _.flattenDeep([1, [2, [3, [4]], 5]]);
* // => [1, 2, 3, 4, 5] * // => [1, 2, 3, 4, 5]
*/ */
function flattenDeep(array) { function flattenDeep(array) {
@@ -5849,20 +5847,25 @@
* @memberOf _ * @memberOf _
* @category Array * @category Array
* @param {Array} array The array to flatten. * @param {Array} array The array to flatten.
* @param {number} depth The maximum recursion depth. * @param {number} [depth=1] The maximum recursion depth.
* @returns {Array} Returns the new flattened array. * @returns {Array} Returns the new flattened array.
* @example * @example
* *
* _.flattenDepth([1, [2, [3, [4]], 5]], 1); * var array = [1, [2, [3, [4]], 5]];
*
* _.flattenDepth(array, 1);
* // => [1, 2, [3, [4]], 5] * // => [1, 2, [3, [4]], 5]
* *
* _.flattenDepth([1, [2, [3, [4]], 5]], 2); * _.flattenDepth(array, 2);
* // => [1, 2, 3, [4], 5] * // => [1, 2, 3, [4], 5]
*/ */
function flattenDepth(array, depth) { function flattenDepth(array, depth) {
depth = toInteger(depth);
var length = array ? array.length : 0; var length = array ? array.length : 0;
return length ? (depth >= 1 ? baseFlatten(array, depth) : copyArray(array)) : []; if (!length) {
return [];
}
depth = depth === undefined ? 1 : toInteger(depth);
return depth < 1 ? copyArray(array) : baseFlatten(array, depth);
} }
/** /**

View File

@@ -5559,25 +5559,48 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.flattenDepth');
(function() {
var array = [1, [2, [3, [4]], 5]];
QUnit.test('should use a default `depth` of `1`', function(assert) {
assert.expect(1);
assert.deepEqual(_.flattenDepth(array), [1, 2, [3, [4]], 5]);
});
QUnit.test('should treat a `depth` of < `1` as a shallow clone', function(assert) {
assert.expect(2);
lodashStable.each([-1, 0], function(depth) {
assert.deepEqual(_.flattenDepth(array, depth), [1, [2, [3, [4]], 5]]);
});
});
QUnit.test('should coerce `depth` to an integer', function(assert) {
assert.expect(1);
assert.deepEqual(_.flattenDepth(array, 2.2), [1, 2, 3, [4], 5]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('flatten methods'); QUnit.module('flatten methods');
(function() { (function() {
var args = arguments; var args = arguments,
array = [1, [2, [3, [4]], 5]];
QUnit.test('should perform a shallow flatten', function(assert) {
assert.expect(1);
var array = [[['a']], [['b']]];
assert.deepEqual(_.flatten(array), [['a'], ['b']]);
});
QUnit.test('should flatten `arguments` objects', function(assert) { QUnit.test('should flatten `arguments` objects', function(assert) {
assert.expect(2); assert.expect(3);
var array = [args, [args]]; var array = [args, [args]];
assert.deepEqual(_.flatten(array), [1, 2, 3, args]); assert.deepEqual(_.flatten(array), [1, 2, 3, args]);
assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 1, 2, 3]); assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 1, 2, 3]);
assert.deepEqual(_.flattenDepth(array, 2), [1, 2, 3, 1, 2, 3]);
}); });
QUnit.test('should treat sparse arrays as dense', function(assert) { QUnit.test('should treat sparse arrays as dense', function(assert) {
@@ -5588,7 +5611,7 @@
expected.push(undefined, undefined, undefined); expected.push(undefined, undefined, undefined);
lodashStable.each([_.flatten(array), _.flatten(array, true), _.flattenDeep(array)], function(actual) { lodashStable.each([_.flatten(array), _.flattenDeep(array), _.flattenDepth(array)], function(actual) {
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
assert.ok('4' in actual); assert.ok('4' in actual);
}); });
@@ -5597,24 +5620,18 @@
QUnit.test('should work with extremely large arrays', function(assert) { QUnit.test('should work with extremely large arrays', function(assert) {
assert.expect(3); assert.expect(3);
// Test in modern browsers only to avoid browser hangs.
lodashStable.times(3, function(index) { lodashStable.times(3, function(index) {
if (freeze) { var expected = Array(5e5);
var expected = Array(5e5); try {
var func = _.flatten;
try { if (index == 1) {
if (index) { func = _.flattenDeep;
var actual = actual == 1 ? _.flatten([expected], true) : _.flattenDeep([expected]); } else if (index == 2) {
} else { func = _.flattenDepth;
actual = _.flatten(expected);
}
assert.deepEqual(actual, expected);
} catch (e) {
assert.ok(false, e.message);
} }
} assert.deepEqual(func([expected]), expected);
else { } catch (e) {
skipTest(assert); assert.ok(false, e.message);
} }
}); });
}); });
@@ -5630,46 +5647,46 @@
}); });
QUnit.test('should support flattening of nested arrays', function(assert) { QUnit.test('should support flattening of nested arrays', function(assert) {
assert.expect(4); assert.expect(3);
var array = [1, [[2, 3], 4, [[[5]]]]]; assert.deepEqual(_.flatten(array), [1, 2, [3, [4]], 5]);
assert.deepEqual(_.flatten(array), [1, [2, 3], 4, [[[5]]]]);
assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 4, 5]); assert.deepEqual(_.flattenDeep(array), [1, 2, 3, 4, 5]);
assert.deepEqual(_.flattenDepth(array, 2), [1, 2, 3, 4, [[5]]]); assert.deepEqual(_.flattenDepth(array, 2), [1, 2, 3, [4], 5]);
assert.deepEqual(_.flattenDepth(array, 3), [1, 2, 3, 4, [5]]);
}); });
QUnit.test('should return an empty array for non array-like objects', function(assert) { QUnit.test('should return an empty array for non array-like objects', function(assert) {
assert.expect(5); assert.expect(3);
var nonArray = { 'a': 1 }; var expected = [],
var expected = []; nonArray = { 'a': 1 };
assert.deepEqual(_.flatten(nonArray), expected); assert.deepEqual(_.flatten(nonArray), expected);
assert.deepEqual(_.flatten(nonArray, true), expected);
assert.deepEqual(_.flattenDeep(nonArray), expected); assert.deepEqual(_.flattenDeep(nonArray), expected);
assert.deepEqual(_.flattenDepth(nonArray, 2), expected); assert.deepEqual(_.flattenDepth(nonArray, 2), expected);
assert.deepEqual(_.flattenDepth(nonArray, 0), expected);
}); });
QUnit.test('should return a wrapped value when chaining', function(assert) { QUnit.test('should return a wrapped value when chaining', function(assert) {
assert.expect(4); assert.expect(6);
if (!isNpm) { if (!isNpm) {
var wrapped = _([1, [2], [3, [4]]]), var wrapped = _(array),
actual = wrapped.flatten(); actual = wrapped.flatten();
assert.ok(actual instanceof _); assert.ok(actual instanceof _);
assert.deepEqual(actual.value(), [1, 2, 3, [4]]); assert.deepEqual(actual.value(), [1, 2, [3, [4]], 5]);
actual = wrapped.flattenDeep(); actual = wrapped.flattenDeep();
assert.ok(actual instanceof _); assert.ok(actual instanceof _);
assert.deepEqual(actual.value(), [1, 2, 3, 4]); assert.deepEqual(actual.value(), [1, 2, 3, 4, 5]);
actual = wrapped.flattenDepth(2);
assert.ok(actual instanceof _);
assert.deepEqual(actual.value(), [1, 2, 3, [4], 5]);
} }
else { else {
skipTest(assert, 4); skipTest(assert, 6);
} }
}); });
}(1, 2, 3)); }(1, 2, 3));