Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Javascript groupby and sum key value

I have the following array of dicts

var response = [{
        "ShoppingCart": "cart1",
        "Class": "Gen",
        "Type": "300",
        "SubClass": "Mens",
        "Points": 0.9
    },
    {
        "ShoppingCart": "cart2",
        "Class": "Lux",
        "Type": "3002C",
        "SubClass": "Mens",
        "Points": 0.75
    },
    {
        "ShoppingCart": "cart3",
        "Class": "Lux",
        "Type": "380",
        "SubClass": "Ladies",
        "Points": 0.5
    },
    {
        "ShoppingCart": "cart4",
        "Class": "Lux",
        "Type": "300",
        "SubClass": "Cabin",
        "Points": 1
    },
    {
        "ShoppingCart": "cart5",
        "Class": "Comfort",
        "Type": "380",
        "SubClass": "Ladies",
        "Points": 1
    },
    {
        "ShoppingCart": "cart6",
        "Class": "Gen",
        "Type": "380",
        "SubClass": "Cabin",
        "Points": 0.9
    },
    {
        "ShoppingCart": "cart7",
        "Class": "Gen",
        "Type": "300",
        "SubClass": "Cabin",
        "Points": 0.7
    },
    {
        "ShoppingCart": "cart8",
        "Class": "Gen",
        "Type": "380PC",
        "SubClass": "Ladies",
        "Points": 0.7
    },
    {
        "ShoppingCart": "cart9",
        "Class": "Lux",
        "Type": "380",
        "SubClass": "Cabin",
        "Points": 0.5
    },
    {
        "ShoppingCart": "cart10",
        "Class": "Lux",
        "Type": "380",
        "SubClass": "Ladies",
        "Points": 0.5
    }
]

I am using reduce function and When i do a groupby and sum the Points , the Class is repeated and not unique , How can i perform a groupby and sum the unique values .
I know lodash’s groupby function solves, how can i do it with the reduce function itself ?
The last Class comfort is not coming in the output , why is that ?

the code so far

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


result = [];

response.reduce(function(res, value) {
    if (!res[value.Type]) {
        res[value.Type] = { Type: value.Type, Class: value.Class, Points: 0 };
        result.push(res[value.Type])
    }
    res[value.Type].Points += parseFloat(value.Points);
    return res;
}, {});

console.log(result);


result:

[
  { Type: '300', Class: 'Gen', Points: 2.5999999999999996 },
  { Type: '3002C', Class: 'Lux', Points: 0.75 },
  { Type: '380', Class: 'Lux', Points: 3.4 },
  { Type: '380PC', Class: 'Gen', Points: 0.7 }
]

expected result:

[
  { Type: '300', Class: 'Gen', Points: 2.5999999999999996 },
  { Type: '3002C', Class: 'Lux', Points: 0.75 },
  { Type: '380', Class: 'Lux', Points: 3.4 },
  { Type: '380PC', Class: 'Gen', Points: 0.7 },
  { Type: '380', Class: 'Comfort', Points: 1 }
]

What am i missing in this reduce function ?

Modified Code as per epascarello’s suggestions

response.reduce(function(res, value) {
    const key = value.Type + "-" + value.Class;
    if (!res[key]) {
        res[key] = { Type: value.Type, Class: value.Class, Points: 0 };
        result.push(res[key])
    }
    res[key].Points += parseFloat(value.Points);
    return res;
}, {});

console.log(result);

>Solution :

I think this is more what you’re looking for.

Basically, for each item in response it will try to find an item in the results array that has the same Type and Class as the provided item. If it finds one it will increment that item’s Points by the provided Points, if not it will append a new item onto the results array.

.reduce is a very useful function, but how you had it before was not utilizing its capabilities.

var response = [{
    "ShoppingCart": "cart1",
    "Class": "Gen",
    "Type": "300",
    "SubClass": "Mens",
    "Points": 0.9
  },
  {
    "ShoppingCart": "cart2",
    "Class": "Lux",
    "Type": "3002C",
    "SubClass": "Mens",
    "Points": 0.75
  },
  {
    "ShoppingCart": "cart3",
    "Class": "Lux",
    "Type": "380",
    "SubClass": "Ladies",
    "Points": 0.5
  },
  {
    "ShoppingCart": "cart4",
    "Class": "Lux",
    "Type": "300",
    "SubClass": "Cabin",
    "Points": 1
  },
  {
    "ShoppingCart": "cart5",
    "Class": "Comfort",
    "Type": "380",
    "SubClass": "Ladies",
    "Points": 1
  },
  {
    "ShoppingCart": "cart6",
    "Class": "Gen",
    "Type": "380",
    "SubClass": "Cabin",
    "Points": 0.9
  },
  {
    "ShoppingCart": "cart7",
    "Class": "Gen",
    "Type": "300",
    "SubClass": "Cabin",
    "Points": 0.7
  },
  {
    "ShoppingCart": "cart8",
    "Class": "Gen",
    "Type": "380PC",
    "SubClass": "Ladies",
    "Points": 0.7
  },
  {
    "ShoppingCart": "cart9",
    "Class": "Lux",
    "Type": "380",
    "SubClass": "Cabin",
    "Points": 0.5
  },
  {
    "ShoppingCart": "cart10",
    "Class": "Lux",
    "Type": "380",
    "SubClass": "Ladies",
    "Points": 0.5
  }
];

var grouped = response.reduce((res, value) => {
  const ext = res.find(({
    Type,
    Class
  }) => {
    return Type === value.Type && Class === value.Class;
  });

  if (ext) {
    ext.Points += value.Points;
  } else {
    res.push({
      Type: value.Type,
      Class: value.Class,
      Points: value.Points
    });
  }

  return res;
}, []);

console.log(grouped);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading