diff --git a/lodash.js b/lodash.js index 39a413ac2..c330b5172 100644 --- a/lodash.js +++ b/lodash.js @@ -1348,6 +1348,7 @@ parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, + push = arrayProto.push, setTimeout = context.setTimeout, splice = arrayProto.splice; @@ -1430,11 +1431,11 @@ * `memoize`, `merge`, `mergeWith` `method`, `methodOf`, `mixin`, `modArgs`, * `modArgsSet', 'negate`, `omit`, `omitBy`, `once`, `pairs`, `partial`, * `partialRight`, `partition`, `pick`, `pickBy`, `plant`, `property`, - * `propertyOf`, `pull`, `pullAt`, `push`, `range`, `rearg`, `reject`, - * `remove`, `rest`, `restParam`, `reverse`, `set`, `setWith`, `shuffle`, - * `slice`, `sort`, `sortBy`, `sortByOrder`, `splice`, `spread`, `take`, - * `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, - * `times`, `toArray`, `toPath`, `toPlainObject`, `transform`, `union`, + * `propertyOf`, `pull`, `pullAll`, `pullAt`, `push`, `range`, `rearg`, + * `reject`, `remove`, `rest`, `restParam`, `reverse`, `set`, `setWith`, + * `shuffle`, `slice`, `sort`, `sortBy`, `sortByOrder`, `splice`, `spread`, + * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, + * `thru`, `times`, `toArray`, `toPath`, `toPlainObject`, `transform`, `union`, * `uniq`, `uniqBy`, `unset`, `unshift`, `unzip`, `unzipWith`, `values`, * `valuesIn`, `without`, `wrap`, `xor`, `zip`, `zipObject`, and `zipWith` * @@ -5156,6 +5157,31 @@ return array; } + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3, 1, 2, 3]; + * + * _.pull(array, [2, 3]); + * console.log(array); + * // => [1, 1] + */ + function pullAll(array, values) { + var args = [array]; + push.apply(args, values); + return pull.apply(undefined, args); + } + /** * Removes elements from `array` corresponding to `indexes` and returns an * array of removed elements. @@ -12184,6 +12210,7 @@ lodash.property = property; lodash.propertyOf = propertyOf; lodash.pull = pull; + lodash.pullAll = pullAll; lodash.pullAt = pullAt; lodash.range = range; lodash.rearg = rearg; diff --git a/test/test.js b/test/test.js index 0cc54668c..6ce0041a3 100644 --- a/test/test.js +++ b/test/test.js @@ -14507,50 +14507,59 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash.pull'); + QUnit.module('pull methods'); - (function() { - QUnit.test('should modify and return the array', function(assert) { + _.each(['pull', 'pullAll'], function(methodName) { + var func = _[methodName], + isPull = methodName == 'pull'; + + function pull(array, values) { + return isPull + ? func.apply(undefined, [array].concat(values)) + : func(array, values); + } + + QUnit.test('`_.' + methodName + '` should modify and return the array', function(assert) { assert.expect(2); var array = [1, 2, 3], - actual = _.pull(array, 1, 3); + actual = pull(array, [1, 3]); assert.deepEqual(array, [2]); assert.ok(actual === array); }); - QUnit.test('should preserve holes in arrays', function(assert) { + QUnit.test('`_.' + methodName + '` should preserve holes in arrays', function(assert) { assert.expect(2); var array = [1, 2, 3, 4]; delete array[1]; delete array[3]; - _.pull(array, 1); + pull(array, [1]); assert.notOk('0' in array); assert.notOk('2' in array); }); - QUnit.test('should treat holes as `undefined`', function(assert) { + QUnit.test('`_.' + methodName + '` should treat holes as `undefined`', function(assert) { assert.expect(1); var array = [1, 2, 3]; delete array[1]; - _.pull(array, undefined); + pull(array, [undefined]); assert.deepEqual(array, [1, 3]); }); - QUnit.test('should match `NaN`', function(assert) { + QUnit.test('`_.' + methodName + '` should match `NaN`', function(assert) { assert.expect(1); var array = [1, NaN, 3, NaN]; - _.pull(array, NaN); + pull(array, [NaN]); assert.deepEqual(array, [1, 3]); }); - }()); + }); /*--------------------------------------------------------------------------*/ @@ -21009,6 +21018,7 @@ 'map', 'pairs', 'pull', + 'pullAll', 'pullAt', 'range', 'reject', @@ -21032,7 +21042,7 @@ var acceptFalsey = _.difference(allMethods, rejectFalsey); QUnit.test('should accept falsey arguments', function(assert) { - assert.expect(241); + assert.expect(243); var emptyArrays = _.map(falsey, _.constant([])); @@ -21052,7 +21062,7 @@ if (methodName == 'noConflict') { root._ = oldDash; } - else if (methodName == 'pull') { + else if (methodName == 'pull' || methodName == 'pullAll') { expected = falsey; } if (_.includes(returnArrays, methodName) && methodName != 'sample') { @@ -21070,7 +21080,7 @@ }); QUnit.test('should return an array', function(assert) { - assert.expect(66); + assert.expect(68); var array = [1, 2, 3]; @@ -21090,7 +21100,7 @@ } assert.ok(_.isArray(actual), '_.' + methodName + ' returns an array'); - var isPull = methodName == 'pull'; + var isPull = methodName == 'pull' || methodName == 'pullAll'; assert.strictEqual(actual === array, isPull, '_.' + methodName + ' should ' + (isPull ? '' : 'not ') + 'return the provided array'); }); });