user10863293
user10863293

Reputation: 876

How can I remove duplicates in an array of object?

I have an array which looks like this :

var array = 
[
    {
        key : { id : 1 , pack : "pack 1"},
        values : [
            {
                item : { id : 1 , name : "item1"},
                itemP : {id : 2 , name : "itemP12"}
            },
            {
                item : { id : 4 , name : "item4"},
                itemP : {id : 2 , name : "itemP12"}
            },
        ]
    }
]

I want to remove duplicate itemP so with a function it will look like this :

var array =
[
    {
        key : { id : 1 , pack : "pack 1"},
        values : [
            {
                item : { id : 1 , name : "item1"},
                itemP : {id : 2 , name : "itemP12"}
            },
            {
                item : { id : 4 , name : "item4"},
                itemP : null
            },
        ]
    }
]

When I try I always have errors. It is possible to do this?

Update

I try to do this :

  console.log(array.map(pack => 
    pack.values.map((item) => {
      var test =  JSON.stringify(item)
      var set = new Set(test)

      return Array.from(set).map((item)=> JSON.parse(item))
      }
    )

  ))

Unexpected end of JSON input

I also try something will filter but it doesn't work:

  console.log(this.package.map(pack => pack.values.filter(
    (value, index , array) => array.itemP.indexOf(value) === index
  )))

Upvotes: 2

Views: 212

Answers (4)

Nick Parsons
Nick Parsons

Reputation: 50954

You can map your array elements to array objects which don't include your duplicates using .map(). For each iteration of .map() you can again use .map() for your inner values array to convert it into an array of objects such that the duplicates are converted to null. Here I have kept a seen object which keeps track of the properties seen and their stringified values. By looping over all the properties in your object (using for...of), you can work out whether or not the key-value pair has been seen before by using the seen object.

The advantage of this approach is that it doesn't just work with one property (ie not just itemP), but it will work with any other duplicating key-value pairs.

See example below:

const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];

const seen = {};
const res = array.map(obj => {
 obj.values = obj.values.map(vobj => {
   for (let p in vobj) {
     vobj[p] = seen[p] === JSON.stringify(vobj[p]) ? null : vobj[p];
     seen[p] = seen[p] || JSON.stringify(vobj[p]);
   }
   return vobj;
 });
 return obj;
});

console.log(res);

For an approach which just removed itemP from all object in accross your array you can use:

const array = [{key:{id:1,pack:"pack 1"},values:[{item:{id:1,name:"item1"},itemP:{id:2,name:"itemP12"}},{item:{id:4,name:"item4"},itemP:{id:2,name:"itemP12"}}]}];

let itemP = "";
const res = array.map(obj => {
  obj.values = obj.values.map(vobj => {
    vobj.itemP = itemP ? null : vobj.itemP;
    if('itemP' in vobj) {
      itemP = itemP || JSON.stringify(vobj.itemP);
    }
    
    return vobj;
  });
  return obj;
});

console.log(res);

Upvotes: 1

Washington Guedes
Washington Guedes

Reputation: 4365

Instead of mapping every key property, I suggest cloning the whole structure and setting the object value as null in the cloned one, avoiding unintentionally mutating the original structure.

function nullifyDupes(array) {
  const clone = JSON.parse(JSON.stringify(array));
  const seen = {};

  clone.forEach(pack => {
    pack.values.forEach(items => {
      for (const item in items) {
        const id = items[item].id;

        if (seen[id]) items[item] = null;
        else seen[id] = true;
      }
    });
  });
  
  return clone;
}

const originalArray = [{
  key : { id : 1 , pack : "pack 1"},
  values : [{
    item : { id : 1 , name : "item1"},
    itemP : {id : 2 , name : "itemP12"}
  },
  {
    item : { id : 4 , name : "item4"},
    itemP : {id : 2 , name : "itemP12"}
  }]
}];

const mutatedArray = nullifyDupes(originalArray);
console.log(mutatedArray);

Upvotes: 1

Adil Liaqat
Adil Liaqat

Reputation: 229

You can use map and an object to check if its already exist. Like

var obj = {}

and loop over values

var values = [
            {
                item : { id : 1 , name : "item1"},
                itemP : {id : 2 , name : "itemP12"}
            },
            {
                item : { id : 4 , name : "item4"},
                itemP : {id : 2 , name : "itemP12"}
            }
        ]

values.map((v) => {
    if(!obj[v.itemP.id + '-' + v.itemP.name]) { 
     obj[v.itemP.id + '-' + v.itemP.name] = true; 
     return v;
    }
    return { item : v.item }

})

Upvotes: 1

Naga Sai A
Naga Sai A

Reputation: 10975

To achieve expected result, use below option of using map

  1. Loop array using map
  2. Use nameArr to check duplicate and assigning null value
  3. Loop values array and check the name in nameArr using indexOf and assign null

var array = [
    {
        key : { id : 1 , pack : "pack 1"},
        values : [
            {
                item : { id : 1 , name : "item1"},
                itemP : {id : 2 , name : "itemP12"}
            },
            {
                item : { id : 4 , name : "item4"},
                itemP : {id : 2 , name : "itemP12"}
            }
        ]
    }
]


console.log(array.map(v => {
  let nameArr = []
  v.values = v.values.map(val => {
    if(nameArr.indexOf(val.itemP.name) !== -1){
      val.itemP.name = null
    }else{
      nameArr.push(val.itemP.name)      
    }
    return val
  })
  return v
}))

Upvotes: 1

Related Questions