Quick Unique Value Filter in JavaScript
Filtering for unique values is a useful operation when processing lists of data that can more information than needed. Dealing with simple values like integers or strings, the process is quite obvious:
function unique(array) { const newArray = []; // A map cannot be used since there may be less items in the new array array.forEach(function(element) { let isDuplicate = false; for (let index = 0; index < newArray.length && isDuplicate === false; index += 1) { isDuplicate = element === newArray[index]; } if (isDuplicate === false) { newArray.push(element); } }); return newArray; } console.log(uniq([1, 2, 2, 3, 3, 4, 5])); // [ 1, 2, 3, 4, 5 ] console.log(uniq([5, 4, 5, 3, 2, 4, 1])); // [ 5, 4, 3, 2, 1 ] console.log(uniq(['test1', 'test1', 'test2'])); // [ 'test1', 'test2' ]
That function maintains the ordering of the original array and always uses the first unique value. Which is similar to (_.uniq from Lodash)[https://lodash.com/docs/4.17.4#uniq].
A very important note; An object key comparison cannot be used to simplify the above. Object keys are always stored as strings with anything being sent into a key being transformed into a string. Meaning objects with different references, but the same contents would be incorrectly labeled as duplicates. The Github source at the bottom of this post gives an example of this.
This basic unique will not handle more complex cases like when deep objects need to be compared on a single property, which is why it needs to be extended to support callbacks that determine uniqueness. For example, data is retrieved from a database that lists all cars and all thier versions, but only the unique car names need to be determined:
const cars = [ { name: 'miata', hp: '115' }, { name: 'miata', hp: '133' }, { name: 'elise', hp: '217' }, { name: 'miata', hp: '155' }, { name: 'elise', hp: '189' }, ]; const uniqueCars = unique(cars, function(carA, carB) { return carB !== undefined && carA.name === carB.name; }); console.log(uniqueCars); // [ { name: 'miata', hp: '115' }, // { name: 'elise', hp: '217' } ] The only part that changed in the original function was a check for if there is a callback: function unique(array, callback) { const newArray = []; const hasCallback = typeof callback === 'function'; // A map cannot be used since there may be less items in the new array array.forEach(function(element, index) { let isDuplicate = false; for (let index = 0; index < newArray.length && isDuplicate === false; index += 1) { if (hasCallback === true) { isDuplicate = callback(element, newArray[index]) === true; } else { isDuplicate = element === newArray[index]; } } if (isDuplicate === false) { newArray.push(element); } }); return newArray; }
This is similar to (_.uniqWith from Lodash)[https://lodash.com/docs/4.17.4#uniqWith]
Github Location: https://github.com/Jacob-Friesen/obscurejs/blob/master/2017/unique.js











