Javascript - Counting duplicates in object array and storing the count as a new object

I have an array of javascript objects that are products. These products are displayed in a list as a cart.

I want to count the number of duplicate products in the array based in the _.id value and remove these objects from the array and relace them with an updated version and a new key called count with a value of the total number of times this object comes up.

So far, I have tried numerous methods and I've searched all over google but there's nothing that I've found that can do the job correctly.

An example of the type of array that I will be using would be this:

[

    {  _id: "5971df93bfef201237985c4d", 
       slug: "5971df93bfef201237985c4d", 
       taxPercentage: 23, 
       totalCost: 9.99, 
       currency: "EUR", 
    },

]

so what I would want my end result to be would be something like this - it removes the duplicate value and replaces it with the same object but adds a new key called count with a value of the number of times the object initially was in the array:

[

    {  _id: "5971df93bfef201237985c4d", 
       slug: "5971df93bfef201237985c4d", 
       taxPercentage: 23, 
       totalCost: 9.99, 
       currency: "EUR", 
       count: 2, // whatever the count is
    },

]

So far I'm using this method:

var count = [];

if (cart.cart.products != undefined) {
    let namestUi = {
        renderNames(names){
            return Array.from(
                names.reduce( (counters, object) =>
                        counters.set(object._id, (counters.get(object._id) || 0) + 1),
                    new Map() ),
                ([object, count]) => {
                    var filterObj = names.filter(function(e) {
                        return e._id == object;
                    });

                    return ({filterObj, count})
                }
            );
        }
    };

    count = namestUi.renderNames(cart.cart.products);
    console.log(count)
}

but it returns the values like this:

{filterObj: Array // the array of the duplicates, count: 2}
{filterObj: Array, count: 1}

and since I am using React-Native with a list view something like this won't work.

It just needs to store the items the way it was before (an array) but with a new child called count.

Any help is welcomed!

Answers:

Answer

I would stick to reduce, use a Map and spread its values to get the final result:

const names = [{  _id: 1 }, { _id: 1}, { _id: 2}, { _id: 1}];

const result = [...names.reduce( (mp, o) => {
    if (!mp.has(o._id)) mp.set(o._id, { ...o, count: 0 });
    mp.get(o._id).count++;
    return mp;
}, new Map).values()];

console.log(result);

When you would have more than one key, then one idea is to join those with JSON.stringify([ ]):

const names = [{cat: 1, sub: 1}, {cat: 1, sub: 2}, {cat: 2, sub: 1}, {cat: 1, sub: 1}];

const result = [...names.reduce( (mp, o) => {
    const key = JSON.stringify([o.cat, o.sub]);
    if (!mp.has(key)) mp.set(key, { ...o, count: 0 });
    mp.get(key).count++;
    return mp;
}, new Map).values()];

console.log(result);

Answer

The easiest would be probably a map:

var map=new Map();

names.forEach(function(el){
 if(map.has(el["_id"])){
  map.get(el["_id"]).count++;
 }else{
  map.set(el["_id"],Object.assign(el,{count:1}));
 }
});  

And then recreate an array:

names=[...map.values()];

Or in old hash/array way:

var hash={},result=[];

names.forEach(function(name){
  var id=name["_id"];
  if(hash[id]){
     hash[id].count++;
  }else{
     result.push(hash[id]={
        count:1,
        ...name
     });
  }
});

console.log(result);
Answer

You can make use of array.reduce method to convert an original array into a new array with desired structure. We can just check if the id exists in the array and accordingly update the array with new object having count property.

let arr = [{
  id: 1
}, {
  id: 1
}, {
  id: 1
}, {
  id: 2
}, {
  id: 2
}];

let new_arr = arr.reduce((ar, obj) => {
  let bool = false;
  if (!ar) {
    ar = [];
  }
  ar.forEach((a) => {
    if (a.id === obj.id) {
      a.count++;
      bool = true;
    }
  });
  if (!bool) {
    obj.count = 1;
    ar.push(obj);
  }
  return ar;
}, []);

console.log(new_arr);

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.