From 055fdfa0b4c6dce2291bd155f01929b89fcd7330 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 25 Feb 2016 22:32:58 -0800 Subject: [PATCH] Add `_.pullAllWith`. --- fp/_mapping.js | 26 ++++++------ lodash.js | 111 +++++++++++++++++++++++++++++++++---------------- test/test.js | 2 +- 3 files changed, 91 insertions(+), 48 deletions(-) diff --git a/fp/_mapping.js b/fp/_mapping.js index b3ac217bf..a5de51640 100644 --- a/fp/_mapping.js +++ b/fp/_mapping.js @@ -55,22 +55,22 @@ exports.aryMethod = { 'hasIn', 'includes', 'indexOf', 'intersection', 'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy', 'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty', 'maxBy', 'merge', 'minBy', 'omit', - 'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', - 'partial', 'partialRight', 'partition', 'pick', 'pickBy', 'pull', 'pullAll', - 'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', - 'repeat', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex', - 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy', - 'split', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight', 'takeRightWhile', - 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars', 'trimCharsEnd', - 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith', 'unset', - 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject', 'zipObjectDeep' + 'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial', + 'partialRight', 'partition', 'pick', 'pickBy', 'pull', 'pullAll', 'pullAt', + 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', 'repeat', 'result', + 'sampleSize', 'some', 'sortBy', 'sortedIndex', 'sortedIndexOf', 'sortedLastIndex', + 'sortedLastIndexOf', 'sortedUniqBy', 'split', 'startsWith', 'subtract', 'sumBy', + 'take', 'takeRight', 'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', + 'times', 'trimChars', 'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', + 'uniqBy', 'uniqWith', 'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', + 'zipObject', 'zipObjectDeep' ], '3': [ 'assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith', 'getOr', 'inRange', 'intersectionBy', 'intersectionWith', 'isEqualWith', - 'isMatchWith', 'mergeWith', 'orderBy', 'pullAllBy', 'reduce', 'reduceRight', - 'replace', 'set', 'slice', 'sortedIndexBy', 'sortedLastIndexBy', 'transform', - 'unionBy', 'unionWith', 'xorBy', 'xorWith', 'zipWith' + 'isMatchWith', 'mergeWith', 'orderBy', 'pullAllBy', 'pullAllWith', 'reduce', + 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy', 'sortedLastIndexBy', + 'transform', 'unionBy', 'unionWith', 'xorBy', 'xorWith', 'zipWith' ], '4': [ 'fill', 'setWith' @@ -137,6 +137,7 @@ exports.methodRearg = { 'isMatchWith': [2, 1, 0], 'mergeWith': [1, 2, 0], 'pullAllBy': [2, 1, 0], + 'pullAllWith': [2, 1, 0], 'setWith': [3, 1, 2, 0], 'sortedIndexBy': [2, 1, 0], 'sortedLastIndexBy': [2, 1, 0], @@ -156,6 +157,7 @@ exports.mutate = { 'pull': true, 'pullAll': true, 'pullAllBy': true, + 'pullAllWith': true, 'pullAt': true, 'remove': true, 'reverse': true diff --git a/lodash.js b/lodash.js index 211a9c6d0..4d40d5e93 100644 --- a/lodash.js +++ b/lodash.js @@ -564,8 +564,7 @@ } /** - * A specialized version of `_.includesWith` for arrays without support for - * specifying an index to search from. + * This function is like `arrayIncludes` except that it accepts a comparator. * * @private * @param {Array} array The array to search. @@ -789,6 +788,28 @@ return -1; } + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + /** * The base implementation of `_.reduce` and `_.reduceRight`, without support * for iteratee shorthands, which iterates over `collection` using `eachFunc`. @@ -811,9 +832,9 @@ } /** - * The base implementation of `_.sortBy` which uses `comparer` to define - * the sort order of `array` and replaces criteria objects with their - * corresponding values. + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. * * @private * @param {Array} array The array to sort. @@ -1441,15 +1462,15 @@ * `methodOf`, `mixin`, `negate`, `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, * `over`, `overArgs`, `overEvery`, `overSome`, `partial`, `partialRight`, * `partition`, `pick`, `pickBy`, `plant`, `property`, `propertyOf`, `pull`, - * `pullAll`, `pullAllBy`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, - * `reject`, `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, - * `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, - * `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, - * `toArray`, `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, - * `unary`, `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, - * `unset`, `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, `without`, - * `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, `zipObject`, `zipObjectDeep`, - * and `zipWith` + * `pullAll`, `pullAllBy`, `pullAllWith`, `pullAt`, `push`, `range`, + * `rangeRight`, `rearg`, `reject`, `remove`, `rest`, `reverse`, `sampleSize`, + * `set`, `setWith`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`, `spread`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, + * `thru`, `toArray`, `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, + * `transform`, `unary`, `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, + * `uniqWith`, `unset`, `unshift`, `unzip`, `unzipWith`, `values`, `valuesIn`, + * `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, `zipObject`, + * `zipObjectDeep`, and `zipWith` * * The wrapper methods that are **not** chainable by default are: * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, @@ -2160,7 +2181,8 @@ } /** - * This function is like `assignValue` except that it doesn't assign `undefined` values. + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. * * @private * @param {Object} object The object to modify. @@ -3282,18 +3304,6 @@ }; } - /** - * The base implementation of `_.pullAll`. - * - * @private - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @returns {Array} Returns `array`. - */ - function basePullAll(array, values) { - return basePullAllBy(array, values); - } - /** * The base implementation of `_.pullAllBy` without support for iteratee * shorthands. @@ -3302,10 +3312,12 @@ * @param {Array} array The array to modify. * @param {Array} values The values to remove. * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns `array`. */ - function basePullAllBy(array, values, iteratee) { - var index = -1, + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, length = values.length, seen = array; @@ -3317,7 +3329,7 @@ value = values[index], computed = iteratee ? iteratee(value) : value; - while ((fromIndex = baseIndexOf(seen, computed, fromIndex)) > -1) { + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { if (seen !== array) { splice.call(seen, fromIndex, 1); } @@ -5577,7 +5589,7 @@ /** * This method is like `_.difference` except that it accepts `iteratee` which * is invoked for each element of `array` and `values` to generate the criterion - * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * by which they're compared. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ @@ -6086,7 +6098,7 @@ /** * This method is like `_.intersection` except that it accepts `iteratee` * which is invoked for each element of each `arrays` to generate the criterion - * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * by which they're compared. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ @@ -6279,7 +6291,7 @@ /** * This method is like `_.pullAll` except that it accepts `iteratee` which is * invoked for each element of `array` and `values` to generate the criterion - * by which uniqueness is computed. The iteratee is invoked with one argument: (value). + * by which they're compared. The iteratee is invoked with one argument: (value). * * **Note:** Unlike `_.differenceBy`, this method mutates `array`. * @@ -6300,7 +6312,35 @@ */ function pullAllBy(array, values, iteratee) { return (array && array.length && values && values.length) - ? basePullAllBy(array, values, getIteratee(iteratee)) + ? basePullAll(array, values, getIteratee(iteratee)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) : array; } @@ -7041,7 +7081,7 @@ /** * This method is like `_.xor` except that it accepts `iteratee` which is * invoked for each element of each `arrays` to generate the criterion by which - * uniqueness is computed. The iteratee is invoked with one argument: (value). + * by which they're compared. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ @@ -14465,6 +14505,7 @@ lodash.pull = pull; lodash.pullAll = pullAll; lodash.pullAllBy = pullAllBy; + lodash.pullAllWith = pullAllWith; lodash.pullAt = pullAt; lodash.range = range; lodash.rangeRight = rangeRight; diff --git a/test/test.js b/test/test.js index a7b2bf295..2821b636d 100644 --- a/test/test.js +++ b/test/test.js @@ -24389,7 +24389,7 @@ var acceptFalsey = lodashStable.difference(allMethods, rejectFalsey); QUnit.test('should accept falsey arguments', function(assert) { - assert.expect(297); + assert.expect(298); var emptyArrays = lodashStable.map(falsey, alwaysEmptyArray);