diff --git a/source/dropRepeatsBy.js b/source/dropRepeatsBy.js new file mode 100644 index 000000000..99040ab99 --- /dev/null +++ b/source/dropRepeatsBy.js @@ -0,0 +1,30 @@ +import _curry2 from './internal/_curry2.js'; +import _dispatchable from './internal/_dispatchable.js'; +import _xdropRepeatsWith from './internal/_xdropRepeatsWith.js'; +import dropRepeatsWith from './dropRepeatsWith.js'; +import eqBy from './eqBy.js'; + + +/** + * Returns a new list without any consecutively repeating elements, + * based upon the value returned by applying the supplied function to + * each list element. [`R.equals`](#equals) is used to determine equality. + * + * Acts as a transducer if a transformer is given in list position. + * + * @func + * @memberOf R + * @category List + * @sig (a -> b) -> [a] -> [a] + * @param {Function} fn A function used to produce a value to use during comparisons. + * @param {Array} list The array to consider. + * @return {Array} `list` without repeating elements. + * @see R.transduce + * @example + * + * R.dropRepeatsBy(Math.abs, [1, -1, -1, 2, 3, -4, 4, 2, 2]); //=> [1, 2, 3, -4, 2] + */ +var dropRepeatsBy = _curry2(function(fn, list) { + return _dispatchable([], _xdropRepeatsWith(eqBy(fn)), dropRepeatsWith(eqBy(fn)))(list); +}); +export default dropRepeatsBy; diff --git a/source/index.js b/source/index.js index 9fb0e437a..86c63f018 100644 --- a/source/index.js +++ b/source/index.js @@ -53,6 +53,7 @@ export { default as drop } from './drop.js'; export { default as dropLast } from './dropLast.js'; export { default as dropLastWhile } from './dropLastWhile.js'; export { default as dropRepeats } from './dropRepeats.js'; +export { default as dropRepeatsBy } from './dropRepeatsBy.js'; export { default as dropRepeatsWith } from './dropRepeatsWith.js'; export { default as dropWhile } from './dropWhile.js'; export { default as either } from './either.js'; diff --git a/test/dropRepeatsBy.js b/test/dropRepeatsBy.js new file mode 100644 index 000000000..7552ceb6b --- /dev/null +++ b/test/dropRepeatsBy.js @@ -0,0 +1,38 @@ +var R = require('../source/index.js'); +var eq = require('./shared/eq.js'); + + +describe('dropRepeatsBy', function() { + var objs = [ + {i: 1}, {i: 2}, {i: 3}, {i: -4}, {i: 5}, {i: 3} + ]; + var objs2 = [ + {i: 1}, {i: -1}, {i: 1}, {i: 2}, {i: 3}, + {i: 3}, {i: -4}, {i: 4}, {i: 5}, {i: 3} + ]; + var fn = ({ i }) => ({ i: Math.abs(i) }); + + it('removes repeated elements based on predicate', function() { + eq(R.dropRepeatsBy(fn, objs2), objs); + eq(R.dropRepeatsBy(fn, objs), objs); + }); + + it('keeps elements from the left', function() { + eq( + R.dropRepeatsBy( + ({ n, ...rest }) => ({ ...rest }), + [{i: 1, n: 1}, {i: 1, n: 2}, {i: 1, n: 3}, {i: 4, n: 1}, {i: 4, n: 2}] + ), + [{i: 1, n: 1}, {i: 4, n: 1}] + ); + }); + + it('returns an empty array for an empty array', function() { + eq(R.dropRepeatsBy(fn, []), []); + }); + + it('can act as a transducer', function() { + eq(R.into([], R.dropRepeatsBy(fn), objs2), objs); + }); + +}); diff --git a/test/dropRepeatsWith.js b/test/dropRepeatsWith.js index cf2153955..00ceac2ec 100644 --- a/test/dropRepeatsWith.js +++ b/test/dropRepeatsWith.js @@ -10,7 +10,7 @@ describe('dropRepeatsWith', function() { {i: 1}, {i: 1}, {i: 1}, {i: 2}, {i: 3}, {i: 3}, {i: 4}, {i: 4}, {i: 5}, {i: 3} ]; - var eqI = R.eqProps('i'); + var eqI = (a, b) => a.i === b.i; it('removes repeated elements based on predicate', function() { eq(R.dropRepeatsWith(eqI, objs2), objs);