how to remove duplicate object from array by comparing two keys in same array?

Viewed 110

I have checked similar questions but they either remove duplicate by using a single key or its comparison between two array of object, here I have an array of object where i want to remove objects if they have same id and and same code. if p_id and c_code is same remove

 const arr = filter(this.campaignArr, el => {
            if (el.p_id== el.p_id && el.c_code== el.c_code) {
              return el;
            }
          });
          console.log(arr)

[{id:"1", p_id:"mobile", c_code:"aaa"},
{id:"1", p_id:"mobile", c_code:"aaa"},
{id:"2", p_id:"electronics", c_code:"aaa"},
{id:"1", p_id:"mobile", c_code:"bbb"},
{id:"2", p_id:"electronics", c_code:"bbb"},
{id:"2", p_id:"electronics", c_code:"bbb"}]

expected output

[{id:"1", p_id:"mobile", c_code:"aaa"},
{id:"2", p_id:"electronics", c_code:"aaa"},
{id:"1", p_id:"mobile", c_code:"bbb"},
{id:"2", p_id:"electronics", c_code:"bbb"}]
4 Answers

Here is one way to do it: filter the array then return the first result that matches using findIndex (dupes will be ignored since it only returns the first match).

const campaignArr = [
  {id:"1", p_id:"mobile", c_code:"aaa"},
  {id:"1", p_id:"mobile", c_code:"aaa"},
  {id:"2", p_id:"electronics", c_code:"aaa"},
  {id:"1", p_id:"mobile", c_code:"bbb"},
  {id:"2", p_id:"electronics", c_code:"bbb"},
  {id:"2", p_id:"electronics", c_code:"bbb"}
]

const newArray = campaignArr.filter((item, index) => {
  const _item = JSON.stringify(item);
  return index === campaignArr.findIndex(obj => {
    return JSON.stringify(obj) === _item;
  });
});

console.log(newArray)

let arr = [{id:"1", p_id:"mobile", c_code:"aaa"},
{id:"1", p_id:"mobile", c_code:"aaa"},
{id:"2", p_id:"electronics", c_code:"aaa"},
{id:"1", p_id:"mobile", c_code:"bbb"},
{id:"2", p_id:"electronics", c_code:"bbb"},
{id:"2", p_id:"electronics", c_code:"bbb"}]

let updatedArr =[];

arr.map((x)=>{
     if(!updatedArr.find((y)=>y.id == x.id && y.c_code == x.c_code)){
         updatedArr.push(x);
     }  
});

console.log(updatedArr);

Create an array, map through the existing arr and find if the object is already present in updated Array. Else, push it the object to new array. Hope this helps!

The problem you're facing now is due to the line:

if (el.p_id== el.p_id && el.c_code== el.c_code)

Which will always hit, since el.p_id== el.p_id && el.c_code== el.c_code is always true because you're comparing the element to itself.

Instead use an Set to store and check which values you've already added. Use a JSON string as unique key. This can be achieved by JSON.stringify an array of the relevant property values.

Then return a falsy value to exclude the current item if the key is present in a set. If the key is not present, add the key to the set and return a truthy value to include the current item.

const campaigns = [
  {id:"1", p_id:"mobile", c_code:"aaa"},
  {id:"1", p_id:"mobile", c_code:"aaa"},
  {id:"2", p_id:"electronics", c_code:"aaa"},
  {id:"1", p_id:"mobile", c_code:"bbb"},
  {id:"2", p_id:"electronics", c_code:"bbb"},
  {id:"2", p_id:"electronics", c_code:"bbb"}
];

const lookup = new Set();
console.log(
  campaigns.filter(campaign => {
    // stringify an array of the properties you want to use for uniqueness
    const key = JSON.stringify([campaign.p_id, campaign.c_code]);
    return !lookup.has(key) && lookup.add(key);
  })
);

Note: IE 11 returns undefined for lookup.add(key) (which is falsy instead of truthy). To make this IE 11 compatible change the line to:

return !lookup.has(key) && (lookup.add(key), true);

Alternatively you could write out the long version, which simultaneously is less cryptic.

if (lookup.has(key)) return false;
lookup.add(key);
return true;

There are other data structures you can use that will guarantee uniqueness. And can solve your problem in a much simpler way. No manual comparisons or complicated iterations. Enter Map

let arr = [
  { id: 1, name: 'Blah' },
  { id: 1, name: 'Blah' },
  { id: 2, name: 'Bleh' } 
];

let map = new Map();
arr.forEach( x => map.set(x.id, x))
console.log(map.values());

Use whatever value is to be considered the unique 'key' and use it as the key in the map. It gives you O(1) read speeds if you know the key but you can also iterate over its values by using the values function to perform array-like operations (or to convert it back to an array).

Edit 1: applied to your specific example:

let arr =[{id:"1", p_id:"mobile", c_code:"aaa"},
{id:"1", p_id:"mobile", c_code:"aaa"},
{id:"2", p_id:"electronics", c_code:"aaa"},
{id:"1", p_id:"mobile", c_code:"bbb"},
{id:"2", p_id:"electronics", c_code:"bbb"},
{id:"2", p_id:"electronics", c_code:"bbb"}]

let map = new Map();
arr.forEach( x => map.set(x.id + x.c_code, x)); // notice the only difference is what the "key" is in this line.
console.log(map.values());
Related