0

I have the following array values,

[
{
    "amount": 4.27,
    "month": 1,
    "year": 2017
},
{
    "amount": 2.46,
    "month": 1,
    "year": 2017
},
{
    "amount": 1.5,
    "month": 2,
    "year": 2017
},
{
    "amount": 28.24,
    "month": 2,
    "year": 2017
},
{
    "amount": 8.24,
    "month": 3,
    "year": 2017
},
{
    "amount": 3.65,
    "month": 3,
    "year": 2017
},
{
    "amount": 0.86,
    "month": 3,
    "year": 2017
},
{
    "amount": 0,
    "month": 1,
    "year": 2018
},
{
    "amount": 71.84,
    "month": 2,
    "year": 2018
},
{
    "amount": 26.62,
    "month": 3,
    "year": 2018
}]

that has to be grouped with respect to specific month and year and the final values should be in the following format,

[
{
    "amount": 6.63,
    "month": 1,
    "year": 2017
},
{
    "amount": 29.74,
    "month": 2,
    "year": 2017
},
{
    "amount":12.75,
    "month": 3,
    "year": 2017
},
{
    "amount": 0,
    "month": 1,
    "year": 2018
},
{
    "amount": 71.84,
    "month": 2,
    "year": 2018
},
{
    "amount": 26.62,
    "month": 3,
    "year": 2018
}]

I have referred this example : Group array items using object

But I cant sort out the summing up part and all I get is only the first value from a particular month and year.

4
  • 6
    Please share your attempt Commented Apr 26, 2018 at 6:30
  • 2
    Please visit the help center, take the tour to see what and How to Ask. Do some research, search for related topics on SO; if you get stuck, post a minimal reproducible example of your attempt, noting input and expected output. Commented Apr 26, 2018 at 6:35
  • is the data sorted? Commented Apr 26, 2018 at 7:04
  • My data is already sorted so I am not facing any sort issues, but .sort doesn't work in Typescript for some reason. Commented Apr 26, 2018 at 7:26

3 Answers 3

2

Use reduce, Object.values and sort

var fnGetKey = (obj) => JSON.stringify({year:obj.year, month:obj.month}); //get key from object
Object.values(arr.reduce( (a,c) => {
  var key = fnGetKey( c );
  !a[key] ? (a[key] = c) : (a[key].amount += c.amount); //Initialize with c if key doesn't exists in accumulator, else increment amount
  return a; //return accumulator
} ,{})).sort( (a,b) => a.year - b.year || a.month - b.month ); //sort by year and month

Demo

var arr = [{
    "amount": 4.27,
    "month": 1,
    "year": 2017
  },
  {
    "amount": 2.46,
    "month": 1,
    "year": 2017
  },
  {
    "amount": 1.5,
    "month": 2,
    "year": 2017
  },
  {
    "amount": 28.24,
    "month": 2,
    "year": 2017
  },
  {
    "amount": 8.24,
    "month": 3,
    "year": 2017
  },
  {
    "amount": 3.65,
    "month": 3,
    "year": 2017
  },
  {
    "amount": 0.86,
    "month": 3,
    "year": 2017
  },
  {
    "amount": 0,
    "month": 1,
    "year": 2018
  },
  {
    "amount": 71.84,
    "month": 2,
    "year": 2018
  },
  {
    "amount": 26.62,
    "month": 3,
    "year": 2018
  }
];

var fnGetKey = (obj) => JSON.stringify({
  year: obj.year,
  month: obj.month
}); //get key from object


var output = Object.values(arr.reduce((a, c) => {
  var key = fnGetKey(c);
  !a[key] ? (a[key] = c) : (a[key].amount += c.amount);
  return a;
}, {})).sort((a, b) => a.year - b.year || a.month - b.month);

console.log(output);

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the solution mate , while what I requested for is working. I would like to know why .sort throws this error [ts] Property 'year' does not exist on type '{}'. any
@Dabber minimal reproducible example please? What's your input? Does that deserve having another question?
1

You can use array#reduce to group your data based on month and year and accumulate all amount in an object in a Map. Then extract all the values and sort the result.

const data = [{ "amount": 4.27, "month": 1, "year": 2017 }, { "amount": 2.46, "month": 1, "year": 2017 }, { "amount": 1.5, "month": 2, "year": 2017 }, { "amount": 28.24, "month": 2, "year": 2017 }, { "amount": 8.24, "month": 3, "year": 2017 }, { "amount": 3.65, "month": 3, "year": 2017 }, { "amount": 0.86, "month": 3, "year": 2017 }, { "amount": 0, "month": 1, "year": 2018 }, { "amount": 71.84, "month": 2, "year": 2018 }, { "amount": 26.62, "month": 3, "year": 2018 } ],
    result = [...data.reduce((r,{amount, month, year}) => {
      const key = month + '/' + year;
      r.has(key) ? r.get(key).amount += amount: r.set(key, {amount, month, year});
      return r;
    },new Map).values()]
    .sort((a,b) => a.year - b.year || a.month - b.month);
console.log(result);

Comments

1

For sorted data, you could check the last item and update the value or push a new object to the result set.

var array = [{ amount: 4.27, month: 1, year: 2017 }, { amount: 2.46, month: 1, year: 2017 }, { amount: 1.5, month: 2, year: 2017 }, { amount: 28.24, month: 2, year: 2017 }, { amount: 8.24, month: 3, year: 2017 }, { amount: 3.65, month: 3, year: 2017 }, { amount: 0.86, month: 3, year: 2017 }, { amount: 0, month: 1, year: 2018 }, { amount: 71.84, month: 2, year: 2018 }, { amount: 26.62, month: 3, year: 2018 }],
    grouped = array.reduce((r, { amount, month, year }) => {
        var last = r[r.length - 1];
        if (last && last.year === year && last.month === month) {
            last.amount += amount;
        } else {
            r.push({ amount, month, year });
        }
        return r;
    }, []);

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.