If you choose not to utilize a library such as lodash or radash, there is an alternative solution using Set as suggested by @Vic. A bug arises when dealing with objects that do not have the same key order. For instance, {a: '1', b: '2'} and {b: '2', a: '1'} are not considered equal strings.
Below is a functional implementation that covers these cases:
Implementation
uniq(source) {
if (!Array.isArray(source)) {
return [];
}
return [...new Set(source.map(o => {
const sortedObjectKeys = Object.keys(o).sort();
const obj = Object.assign({}, ...sortedObjectKeys.map(k => ({[k]: o[k]})) as any);
return JSON.stringify(obj);
}))]
.map(s => JSON.parse(s));
}
Test cases
describe(`uniq`, () => {
it('should return unique collection values', () => {
expect(uniq([{v: 1}, {v: 2}, {v: 1}])).toEqual([{v: 1}, {v: 2}]);
});
it('should return unique collection values for unsorted properties', () => {
expect(uniq([{a: 'test', v: 1}, {v: 2}, {v: 1, a: 'test'}])).toEqual([{a: 'test', v: 1}, {v: 2}]);
});
it('should return empty array for non array source', () => {
expect(uniq({v: 1})).toEqual([]);
expect(uniq('aString')).toEqual([]);
expect(uniq(125)).toEqual([]);
expect(uniq(true)).toEqual([]);
expect(uniq([])).toEqual([]);
expect(uniq(undefined)).toEqual([]);
expect(uniq(null)).toEqual([]);
});
});