skip to Main Content

I’m trying to reduce the an array of Expenses:

interface Expense {
price: number,
date: number,
category: {
name: string
}
}

So that I get an array of objects where each date is unique and the properties are added on if a new one is found.

So basically I want to turn:

[{date: 1, price: 300, category: 'Bills'}, {date: 1, price: 20, category: 'Entertainment'}] 

into:

[ {date: 1, Bills: 300, Entertainment: 20 } ]

Here’s what I have, except it’s creating a new object if the date already exists, instead of adding to the current object:

const newData = months.reduce(
    (acc, curr) => {
      for (let i = 0; i < acc.length; i++) {
        if (curr.date === acc[i].date) {
          return [
            ...acc,
            {
              ...acc[i],
              date: curr.date,
              [curr.category.name]: curr.price,
            },
          ];
        }
      }
      return [
        ...acc,
        {
          date: curr.date,
          [curr.category.name]: curr.price,
        },
      ];
    },
    [{ date: 0 }]
  );

So my output is this instead:

  Array(10) [
    { date: 0 }, { date: 0, Entertainment: 100 }, { date: 1, Entertainment: 30 }, { date: 1, Entertainment: 30, School: 80 },
    { date: 2, Health: 40 }, { date: 3, Food: 200 }, { date: 4, Transportation: 70 }, { date: 5, Bills: 900 }, { date: 6, Food: 5 },
    { date: 6, Food: 5, Health: 50 }
  ]

I’m super close, but I’m not sure how to fix

2

Answers


  1. You could reduce with the help of an object for grouping dates.

    const
        months = [{ date: 1, price: 300, category: 'Bills' }, { date: 1, price: 20, category: 'Entertainment' }],
        result = Object.values(months.reduce((r, { date, price, category }) => {
            (r[date] ??= { date })[category] ??= 0;
            r[date][category] += price;
            return r;
        }, {}));
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    Login or Signup to reply.
  2. const sampleData = [{
      date: 1, price: 300, category: 'Bills',
    }, {
      date: 1, price: 20, category: 'Entertainment',
    }, {
      date: 2, price: 200, category: 'Bills',
    }, {
      date: 2, price: 30, category: 'Entertainment',
    }];
    
    console.log(
      Object
        .values(
          sampleData
            .reduce((index, { date, price: key, category: value }) => {
    
              Object.assign(
                // - create and assign or access object.
                (index[date] ??= { date }),
                // - aggregate the `date` specific object.
                { [ key ]: value },
              );
              return index;
    
            }, {})
        )
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search