From 124db289912dcd04e8a5d9bb0144e38178bd3fb5 Mon Sep 17 00:00:00 2001 From: Johnny Reina Date: Thu, 24 Jan 2019 21:07:08 -0600 Subject: [PATCH] Adds distinct (#81) Closes #8 --- index.d.ts | 3 +++ index.js | 2 ++ src/Distinct.js | 24 ++++++++++++++++++++++++ test/Distinct.spec.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 src/Distinct.js create mode 100644 test/Distinct.spec.js diff --git a/index.d.ts b/index.d.ts index c6a8e44..674ef75 100644 --- a/index.d.ts +++ b/index.d.ts @@ -12,6 +12,9 @@ interface Array { Contains(element: T): boolean; Count(): number; Count(predicate: (x: T) => boolean): number; + Distinct(): Array; + Distinct(): Array; + Distinct(equalityComparer: IEqualityComparer): Array; ElementAt(index: number): T; First(): T; First(predicate: (x: T) => boolean): T; diff --git a/index.js b/index.js index 694d592..c8b4c2b 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,7 @@ const Average = require('./src/Average'); const Concat = require('./src/Concat'); const Contains = require('./src/Contains'); const Count = require('./src/Count'); +const Distinct = require('./src/Distinct'); const ElementAt = require('./src/ElementAt'); const Empty = require('./src/Empty'); const First = require('./src/First'); @@ -42,6 +43,7 @@ const bindAll = function() { Array.prototype.Concat = Concat; Array.prototype.Contains = Contains; Array.prototype.Count = Count; + Array.prototype.Distinct = Distinct; Array.prototype.ElementAt = ElementAt; Array.Empty = Empty; Array.prototype.First = First; diff --git a/src/Distinct.js b/src/Distinct.js new file mode 100644 index 0000000..6e78704 --- /dev/null +++ b/src/Distinct.js @@ -0,0 +1,24 @@ +const _defaultEqualityComparer = require('./.internal/_defaultEqualityComparer'); + +// Distinct(IEnumerable) +// Distinct(IEnumerable, IEqualityComparer) + +/** + * @template T + * @returns {Array} + */ + +/** + * @template T + * @param {(a: T, b: T) => boolean} equalityComparer + * @returns {Array} + * @this {Array} + */ +function Distinct(equalityComparer = _defaultEqualityComparer) { + return this.filter((val, idx, arr) => { + const foundIdx = this.findIndex(v => equalityComparer(v, val)); + return foundIdx === idx; + }); +} + +module.exports = Distinct; diff --git a/test/Distinct.spec.js b/test/Distinct.spec.js new file mode 100644 index 0000000..6680c77 --- /dev/null +++ b/test/Distinct.spec.js @@ -0,0 +1,42 @@ +const expect = require('chai').expect; +require('..')(); + +describe('Array#prototype#Distinct', function() { + it('Should return distinct elements for an array of numbers', function() { + const input = [1, 2, 3, 3, 3, 5, 5]; + const expected = [1, 2, 3, 5]; + const actual = input.Distinct(); + expect(actual).to.eql(expected); + }); + + it('Should return distinct elements for an array of strings', function() { + const input = ['hello', 'hello', 'world', '!']; + const expected = ['hello', 'world', '!']; + const actual = input.Distinct(); + expect(actual).to.eql(expected); + }); + + it('Should return distinct elements for an array of objects when comparing their references', function() { + const obj1 = { _id: 2, name: 'Bernie' }; + const obj2 = { _id: 3, name: 'Susan' }; + const input = [obj1, obj2, obj1]; + const expected = [obj1, obj2]; + + const actual = input.Distinct(); + + expect(actual).to.eql(expected); + }); + + it('Should return distinct elements for an array of objects when comparing their _id values', function() { + const input = [ + { _id: 2, name: 'Bernie' }, + { _id: 3, name: 'Susan' }, + { _id: 2, name: 'Terry' } + ]; + const expected = [{ _id: 2, name: 'Bernie' }, { _id: 3, name: 'Susan' }]; + + const actual = input.Distinct(({ _id: id1 }, { _id: id2 }) => id1 === id2); + + expect(actual).to.eql(expected); + }); +});