0

I have an array with many objects (Drugs). each object has 3 keys: "Drug1", "Drug2", and riskingRate. How can i remove duplicated objects if Drug1 and Drug2 values are same (riskingRate is not important in finding duplicats). then keep object with higher riskingRate and remove others. here is a simple array:

var Warfarin = [{
    "Drug1": "Warfarin",
    "Drug2": "vitamin K",
    "riskRating": "C",
}, {
    "Drug": "aspirin",
    "Drug2": "MiFEPRIStone",
    "riskRating": "C",
}, {
    "Drug1": "Warfarin",
    "Drug2": "Omacetaxine",
    "riskRating": "X",
}, {
    "Drug1": "Warfarin",
    "Drug2": "vitamin K",
    "riskRating": "X",
},{
    "Drug1": "Warfarin",
    "Drug2": "vitamin K",
    "riskRating": "A",
}]

in this example objects 0, 3 and 4 are duplicated and the object 3 has a higher riskingRate. (riskingRate X>D>C>B>A). how can I remove objects 0 and 4 and keep objects 1,2 and 3. Thanks.

Shota
  • 6,910
  • 9
  • 37
  • 67
  • Looks like [Array reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) is a good fit here. – Mike Ezzati Feb 28 '18 at 21:22
  • Is it intentional that the second element has `Drug` and not `Drug1` as a key name? – arvi1000 Feb 28 '18 at 21:33
  • Possible duplicate of [Remove duplicates from an array of objects in JavaScript](https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript) – Heretic Monkey Feb 28 '18 at 21:33

2 Answers2

3

You can do something like this:

var weights = ["X", "D", "C", "B", "A"];

var Warfarin = [{
    "Drug1": "Warfarin",
    "Drug2": "vitamin K",
    "riskRating": "C",
}, {
    "Drug": "aspirin",
    "Drug2": "MiFEPRIStone",
    "riskRating": "C",
}, {
    "Drug1": "Warfarin",
    "Drug2": "Omacetaxine",
    "riskRating": "X",
}, {
    "Drug1": "Warfarin",
    "Drug2": "vitamin K",
    "riskRating": "X",
},{
    "Drug1": "Warfarin",
    "Drug2": "vitamin K",
    "riskRating": "A",
}];

var response = Warfarin.sort((v1, v2) => (weights.indexOf(v1.riskRating) - weights.indexOf(v2.riskRating)))
.reduce((a, c)=>{
    if(!a.some(v => (v.Drug1 == c.Drug1 && v.Drug2 == c.Drug2))){
        a.push(c);
    }
    return a;
}, []);

console.log(response);

What this does is to first sort the array based on the objects' riskRating so the higher risk objects will be at the start, then just reduce the array and don't include the duplicates in the resulting array.

Titus
  • 22,031
  • 1
  • 23
  • 33
3

Here is a solution without sorting, but with an ES6 Map, which would make it run in O(n) time instead of O(nlogn):

const Warfarin = [{"Drug1": "Warfarin","Drug2": "vitamin K","riskRating": "C",}, {"Drug": "aspirin","Drug2": "MiFEPRIStone","riskRating": "C",}, {"Drug1": "Warfarin","Drug2": "Omacetaxine","riskRating": "X",},{"Drug1": "Warfarin","Drug2": "vitamin K","riskRating": "X",},{"Drug1": "Warfarin","Drug2": "vitamin K","riskRating": "A",}];

const result = Array.from(Warfarin.reduce ( (acc, obj) => {
    const key = JSON.stringify([obj.Drug1,obj.Drug2]);
    return !acc.has(key) || acc.get(key).riskRating < obj.riskRating
        ? acc.set(key, obj) : acc; 
}, new Map).values());

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Why `JSON.stringify([obj.Drug1,obj.Drug2])` as the key, and not just `[obj.Drug1,obj.Drug2]`, since Maps don't require keys to be strings? – arvi1000 Feb 28 '18 at 22:42
  • 1
    Because if you pass a new array as key, it will *always* be considered different (comparison will be by reference). – trincot Feb 28 '18 at 22:44