How to group ID's for duplicate object and remove object in array using javascript

Viewed 143

I want to remove duplicate object from array after grouping duplicate object id from matched(already existing) object id. Whatever i have tried that's grouping ID's but not getting how to remove duplicate object from array.

Original Array

        [
         {id:2,title:'men'},
         {id:3,title:'women'},
         {id:1,title:'kids'},
         {id:4,title:'sports'}, 
         {id:5, title:'women'},
         {id:6,title:'kids'}
       ];

Expected Array

 [
   { id: 2, title: 'men' },
   { id: [3,5], title: 'women' },
   { id: [1,6], title: 'kids' },
   { id: 4, title: 'sports' }
 ]

Tried

let array = [{id:2,title:'men'},{id:3,title:'women'},{id:1,title:'kids'},
{id:4,title:'sports'}, {id:5, title:'women'},{id:6,title:'kids'}];

for(let i=0; i<array.length-1;i++){
    for(let j=i+1; j<array.length; j++){
        if(array[i].title===array[j].title)
         array[i]={id:[array[i].id, array[j].id], title: array[i].title}
    }
}
console.log(array)

Please help to achieve expected result in better way.

3 Answers

const arr = [ {id:2,title:'men'}, {id:3,title:'women'}, {id:1,title:'kids'}, {id:4,title:'sports'}, {id:5, title:'women'}, {id:6,title:'kids'} ];

const res = [...
// iterate over arr while updating a Map
arr.reduce((map, item) => {
  const { id, title } = item;
  const prev = map.get(title);
  // if map already contains a record with this title as key, update id list
  if(prev) prev.id = Array.isArray(prev.id) ? [...prev.id, id] : [prev.id, id];
  // else create a new record
  else map.set(title, item);
  return map;
}, new Map)
// after getting the map of grouped items by title, return the values
.values()];

console.log(res);

let items = [{
        id: 2,
        title: 'men'
    },
    {
        id: 3,
        title: 'women'
    },
    {
        id: 1,
        title: 'kids'
    },
    {
        id: 4,
        title: 'sports'
    },
    {
        id: 5,
        title: 'women'
    },
    {
        id: 6,
        title: 'kids'
    }
];

let dest = [];

items.forEach(x => {
    let find;
    if (find = dest.find(y => y.title === x.title)) {
        find.id = Array.isArray(find.id) ? [...find.id, x.id] : [find.id, x.id]
    } else {
        dest.push(x)
    }
})

console.log(dest)

It is easier to create reverse object first with { [title]: keys[] } using reduce then map it back to your required array

const input = [
  { id: 2, title: "men" },
  { id: 3, title: "women" },
  { id: 1, title: "kids" },
  { id: 4, title: "sports" },
  { id: 5, title: "women" },
  { id: 6, title: "kids" },
];

const output = input.reduce((acc, { id, title }) => {
  const val = acc[title];
  if (val) {
    acc[title] = Array.isArray(val) ? [...val, id] : [val, id];
  } else {
    acc[title] = id;
  }
  return acc;
}, {});

const result = Object.keys(output).map((key) => ({
  id: output[key],
  title: key,
}));

console.log(result);

Related