JavaScript: Remove duplicates of objects sharing same property value

Lauren F picture Lauren F · Aug 27, 2015 · Viewed 44.2k times · Source

I have an array of objects that I would like to trim down based on a specific key:value pair. I want to create an array that includes only one object per this specific key:value pair. It doesn't necessarily matter which object of the duplicates is copied to the new array.

For example, I want to trim based on the price property of arrayWithDuplicates, creating a new array that only includes one of each value:

var arrayWithDuplicates = [
  {"color":"red", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 10
    }
  },
  {"color":"green", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 30
    }
  },
  {"color":"blue", 
    "size": "medium",
    "custom": {
      "inStock": true,
      "price": 30
    }
  },
  {"color":"red", 
    "size": "large",
    "custom": {
      "inStock": true,
      "price": 20
    }
  }
];

Would become:

var trimmedArray = [
  {"color":"red", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 10
    }
  },
  {"color":"green", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 30
    }
  },
  {"color":"red", 
    "size": "large",
    "custom": {
      "inStock": true,
      "price": 20
    }
  }
];

Is there a JavaScript or Angular function that would loop through and do this?

EDIT: The property to filter on is nested within another property.

Answer

Tamas Hegedus picture Tamas Hegedus · Aug 27, 2015

This function removes duplicate values from an array by returning a new one.

function removeDuplicatesBy(keyFn, array) {
    var mySet = new Set();
    return array.filter(function(x) {
        var key = keyFn(x), isNew = !mySet.has(key);
        if (isNew) mySet.add(key);
        return isNew;
    });
}

var values = [{color: "red"}, {color: "blue"}, {color: "red", number: 2}];
var withoutDuplicates = removeDuplicatesBy(x => x.color, values);
console.log(withoutDuplicates); // [{"color": "red"}, {"color": "blue"}]

So you could use it like

var arr = removeDuplicatesBy(x => x.custom.price, yourArrayWithDuplicates);