[FIXED] Creating an array of objects with cumulative sum in javascript

Issue

I have this original array that i need to transform into the one named original.

const data =  [ {
end_date: "2020-01-31"
invoices_count: 22
month: "2020-01"
start_date: "2020-01-01"
total_margin: 1000
total_revenue: 1000
},
{
end_date: "2020-02-29"
invoices_count: 14
month: "2020-02"
start_date: "2020-02-01"
total_margin: 2000
total_revenue: 2000
}]

i need to accumulate the total_margin and total_revenue over time, so that the result is equal to the previous month + current month value, so the resulting array will look like this :

const result =  [ {
end_date: "2020-01-31"
invoices_count: 22
month: "2020-01"
start_date: "2020-01-01"
total_margin: 1000
total_revenue: 1000
},
{
end_date: "2020-02-29"
invoices_count: 14
month: "2020-02"
start_date: "2020-02-01"
total_margin: 3000
total_revenue: 3000
}]

I wrote this function to do this, but its modifying the first value in the array as well( total_margin & total_margin at index 0 ) , and the numbers don’t really add up to the correct value, i am not sure what i am doing wrong

export const getCumulativeValueMonth = (data: MonthlyRevenue[]): MonthlyRevenue[] => {
  const orderedData = _.orderBy(data, (o) => Date.parse(o.start_date), ['asc']);
  const accumulated = orderedData.map((x, i) => ({
    start_date: x.start_date,
    end_date: x.end_date,
    invoices_count: x.invoices_count,
    month: x.month,
    total_margin: data
      .slice(0, i + 1)
      .map(({ total_margin }) => total_margin)
      .reduce((z, y) => z + y),
    total_revenue: data
      .slice(0, i + 1)
      .map(({ total_revenue }) => total_revenue)
      .reduce((z, y) => z + y),
  }));
  return accumulated;
};

Any ideas what i did wrong?

Thank you!

Solution

You are slicing the original array data, but you need to take the sorted accumulated.


For a shorter approach, you could take a closure over the wanted cumulative sums and add the values and return a new object.

const
    original = [{ end_date: "2020-01-31", invoices_count: 22, month: "2020-01", start_date: "2020-01-01", total_margin: 1000, total_revenue: 1000 }, { end_date: "2020-02-29", invoices_count: 14, month: "2020-02", start_date: "2020-02-01", total_margin: 2000, total_revenue: 2000 }],
    result = original.map(((total_margin, total_revenue) => o => {
        total_margin += o.total_margin;
        total_revenue += o.total_revenue;
        return { ...o, total_margin, total_revenue };
    })(0, 0));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

With different keys.

const
    original = [{ end_date: "2020-01-31", invoices_count: 22, month: "2020-01", start_date: "2020-01-01", total_margin: 1000, total_revenue: 1000 }, { end_date: "2020-02-29", invoices_count: 14, month: "2020-02", start_date: "2020-02-01", total_margin: 2000, total_revenue: 2000 }],
    result = original.map(((margin, revenue) =>
        ({ total_margin, total_revenue, ...o }) =>
            {
                margin += total_margin;
                revenue += total_revenue;
                return { ...o, margin, revenue };
            }
        )(0, 0)
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answered By – Nina Scholz

Answer Checked By – Pedro (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published