How to Filter Unique Objects by a Property Value in JavaScript

May 18 2025

javascript

TLDR

js
1.const getUniqueBy = (arr, prop) => {
2. const seen = new Set();
3.
4. return arr.filter(item => {
5. const value = item[prop];
6. if (seen.has(value)) {
7. return false;
8. }
9. seen.add(value);
10. return true;
11. });
12.}

Usage

js
1.const users = [
2. { id: 1, name: 'John', age: 30 },
3. { id: 2, name: 'Jane', age: 25 },
4. { id: 3, name: 'John', age: 40 }, // Duplicate name
5. { id: 4, name: 'Bob', age: 35 }
6.];
7.
8.const uniqueByName = getUniqueBy(users, 'name');
9.
10.// Result:
11.// [
12.// { id: 1, name: 'John', age: 30 },
13.// { id: 2, name: 'Jane', age: 25 },
14.// { id: 4, name: 'Bob', age: 35 }
15.// ]

Filter Unique Objects Using Set and Filter: using Set()

When working with arrays of objects in JavaScript, we often need to filter out duplicate objects based on the value of a specific property. Unlike simple arrays where we can use a Set directly, objects require a bit more work since they are compared by reference, not by value. Let's say we have this data:

js
1.const users = [
2. { id: 1, name: 'John', age: 30 },
3. { id: 2, name: 'Jane', age: 25 },
4. { id: 3, name: 'John', age: 40 }, // Duplicate name
5. { id: 4, name: 'Bob', age: 35 }
6.];

The most efficient approach is to combine Set to track which property values we've already seen. Then use the filter() method to create a new array with only the unique objects.

js
1.
2.const getUniqueBy = (arr, prop) => {
3. // Create a Set to track unique property values
4. const seen = new Set();
5.
6. return arr.filter(item => {
7. const isDuplicate = seen.has(user.name); // This is O(1) check vs O(n) for find()
8. if (isDuplicate) {
9. return false; // Skip this item because it's a duplicate
10. }
11. seen.add(value);
12. return true;
13. });
14.};
15.
16.const uniqueByName = getUniqueBy(users, 'name');
17.

The filter() method creates a new array with items that pass the test. In this case, we only keep an item if its property value hasn't been seen before.

Time: O(n) for the filter() method and O(1) for the Set() object.

Space: O(n) for the Set object.

Alternative 1: Map and Object.values()

Another approach uses Map to keep the last instance of each unique value:

js
1.const getUniqueByMap = (arr, prop) => {
2. const map = new Map();
3.
4. arr.forEach(item => {
5. map.set(item[prop], item);
6. });
7.
8. return Array.from(map.values());
9.};
10.
11.const users = [
12. { id: 1, name: 'John', age: 30 },
13. { id: 2, name: 'Jane', age: 25 },
14. { id: 3, name: 'John', age: 40 }, // Duplicate name
15. { id: 4, name: 'Bob', age: 35 }
16.];
17.
18.const uniqueUsers = getUniqueByMap(users, 'name');
19.// Now keeps the LAST John (age 40) instead of the first

This approach differs slightly in that it keeps the last occurrence of each unique property value instead of the first.

Time: O(n) for the forEach() method and O(1) for the Map() object.

Space: O(n) for the Map object.

Alternative 2: the reduce() Method

We can also solve this problem using the reduce() method, which is useful when you want more control over how duplicates are handled:

js
1.const getUniqueByReduce = (arr, prop) => {
2. return arr.reduce((acc, current) => {
3. const isDuplicate = acc.find(item => item[prop] === current[prop]);
4. if (!isDuplicate) {
5. return acc.concat([current]);
6. }
7. return acc;
8. }, []);
9.};
10.
11.const uniqueUsers = getUniqueByReduce(users, 'name');

Time: O(n) for the reduce() method and O(n) for the find() method. Combined this is O(n^2) because the find() method has to traverse the array for each item in the acc array.

Space: O(n) for the acc array.

Alternative 3: the .find() method

You can also use the find() method to check for duplicates:

js
1.const getUniqueByFind = (arr, prop) => {
2. return arr.filter((item, index) => {
3. return arr.findIndex(obj => obj[prop] === item[prop]) === index;
4. }
5.};
6.const uniqueUsers = getUniqueByFind(users, 'name');

This method checks if the index of the first occurrence of the property value is the same as the current index. If it is, we keep the item. Otherwise, we skip it. This is less efficient than using a Set because it has to traverse the array multiple times.

Time: O(n) for the filter() method and O(n) for the find() method. Combined this is O(n^2) because the find() method has to traverse the array for each item in the arr array.

Space: O(n) for the arr array.

Alternative 4: Using a Plain Object

You can also use a plain object to track unique values:

js
1.const getUniqueByObject = (arr, prop) => {
2. const seen = {};
3. return arr.filter(item => {
4. const value = item[prop];
5. if (seen[value]) {
6. return false; // Skip this item because it's a duplicate
7. }
8. seen[value] = true;
9. return true;
10. }
11.};
12.const uniqueUsers = getUniqueByObject(users, 'name');

This method is similar to the Set approach, but it uses a plain object to track seen values. This is less efficient than using a Set because it has to convert the property value to a string, which can be slower for large arrays.

Time: O(n) for the filter() method and O(1) for the Object object.

Space: O(n) for the Object object.

Alternative 5: Lodash's uniqBy

If you're using Lodash, you can use the uniqBy() method, which is a convenient way to achieve the same result:

js
1.import { uniqBy } from 'lodash';
2.const uniqueUsers = uniqBy(users, 'name');

This method is very efficient and easy to use, but it does require including the Lodash library in your project.

Time: O(n) for the uniqBy() method.

Space: O(n) for the uniqBy() method.

Performance Considerations

The Set and Map methods are generally the most efficient for filtering unique objects by property value. The reduce() and find() methods can be less efficient due to their O(n^2) time complexity.