Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript reduce object array by specific value

Tags:

typescript

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.

like image 601
ZGanchev Avatar asked Sep 08 '25 03:09

ZGanchev


2 Answers

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.

like image 145
Fenton Avatar answered Sep 11 '25 12:09

Fenton


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}]
like image 39
XouDo Avatar answered Sep 11 '25 13:09

XouDo