3

I have this:

0: {orderType: "orderType1", orderCount: 0, orderDate: 47}
1: {orderType: "orderType1", orderCount: 21, orderDate: 47}
2: {orderType: "orderType1", orderCount: 3, orderDate: 47}
3: {orderType: "orderType1", orderCount: 5, orderDate: 48}
4: {orderType: "orderType1", orderCount: 32, orderDate: 48}
5: {orderType: "orderType1", orderCount: 12, orderDate: 48}

and I would like to achieve this:

0: {orderType: "orderType1", orderCount: 24, orderDate: 47}
1: {orderType: "orderType1", orderCount: 49, orderDate: 48}

Basically I want to 'combine' or 'reduce' the entries by combining the orderCount based on orderDate.

Apologies if combine or reduce are not the right terms here.

ZGanchev
  • 35
  • 1
  • 1
  • 6
  • 1
    For future readers, this is basically a duplication of this question: https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects check out the answer there for a cleaner solution – Tal Joffe Dec 27 '21 at 13:00

2 Answers2

6

Someone smarter than me can probably do this more succinctly, but if I group the data and then reduce it I can get the desired result.

I have a feeling this could be done in fewer steps:

function setFilter(value, index, self) { 
    return self.indexOf(value) === index;
}

function groupBy(objectArray, property) {
  return objectArray.reduce(function (acc, obj) {
    var key = obj[property];
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(obj);
    return acc;
  }, {});
}

const data = [
    { orderType: "orderType1", orderCount: 0, orderDate: 47 },
    { orderType: "orderType1", orderCount: 21, orderDate: 47 },
    { orderType: "orderType1", orderCount: 3, orderDate: 47 },
    { orderType: "orderType1", orderCount: 5, orderDate: 48 },
    { orderType: "orderType1", orderCount: 32, orderDate: 48 },
    { orderType: "orderType1", orderCount: 12, orderDate: 48 }
];

const groupedData = groupBy(data, 'orderDate');
const reducedData = [];

for (let key in groupedData) {
    let initialValue = 0;
    let sum = groupedData[key].reduce((accumulator, currentValue) => {
        return accumulator + currentValue.orderCount;
    },initialValue)

    reducedData.push({
        orderType: groupedData[key][0].orderType,
        orderCount: sum,
        orderDate: key
    });
}

console.log(reducedData);

This doesn't take into account orderType and I feel it ought to.

Fenton
  • 241,084
  • 71
  • 387
  • 401
  • Worked like a charm. orderType can be omitted,, it's being filtered on an upper level. I've made small adjustment here: `for (let key in groupedData) {` changed to `for (const key of Object.keys(groupedData)) {` Thank you very much! – ZGanchev Nov 27 '18 at 11:38
1

Here is a (slightly) shorter version also using reduce :

 const data = [
    { orderType: "orderType1", orderCount: 0, orderDate: 47 },
    { orderType: "orderType1", orderCount: 21, orderDate: 47 },
    { orderType: "orderType1", orderCount: 3,  orderDate: 47 },
    { orderType: "orderType1", orderCount: 5,  orderDate: 48 },
    { orderType: "orderType1", orderCount: 32, orderDate: 48 },
    { orderType: "orderType1", orderCount: 12, orderDate: 48 }];

let foundIdx;

var result = data.reduce((accu, curr, idx, arr) => {
    if (accu.some((value, resIdx, reArr) => {  // present in out array?
        foundIdx = resIdx;        
        return (value.orderType == curr.orderType && value.orderDate == curr.orderDate);
    }))
    {    // already present, increment OrderCount
        accu[foundIdx].orderCount += curr.orderCount;
    }
    else {   // not yet present push the element
        accu.push(curr);
    }
    return accu;
}, []);

console.log(JSON.stringify(result));
//[{"orderType":"orderType1","orderCount":24,"orderDate":47},{"orderType":"orderType1","orderCount":49,"orderDate":48}]
XouDo
  • 945
  • 10
  • 19