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

后端 未结 3 739
-上瘾入骨i
-上瘾入骨i 2020-12-03 20:01

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 ar

相关标签:
3条回答
  • 2020-12-03 20:10

    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);

    0 讨论(0)
  • 2020-12-03 20:22

    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);
    
    0 讨论(0)
  • 2020-12-03 20:35

    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);

    Or you can first create all the keys in the map with a zero count (using the Map constructor), and then iterate the data again to update the counter. This split of tasks makes the code more concise than with reduce:

    const names = [{  _id: 1 }, { _id: 1}, { _id: 2}, { _id: 1}];
    
    const mp = new Map(names.map(o => [o._id, {...o, count: 0 }]));
    for (const {_id} of names) mp.get(_id).count++;
    const result = Array.from(mp.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);

    0 讨论(0)
提交回复
热议问题