Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort grouped objects by Lodash

I have following array of objects:

[{
   id: 1,
   amount: 2000,
   date: "2018-01-31T00:00:00.000Z"
},{
   id: 2,
   amount: 3000,
   date: "2017-07-31T00:00:00.000Z"
},{
   id: 3,
   amount: 6000,
   date: "2018-01-31T00:00:00.000Z"
},{
   id: 4,
   amount: 7000,
   date: "2017-01-31T00:00:00.000Z"
},{
   id: 5,
   amount: 5000,
   date: "2017-03-31T00:00:00.000Z"
},{
   id: 6,
   amount: 3000,
   date: "2018-02-22T00:00:00.000Z"
},{
   id: 7,
   amount: 4500,
   date: "2017-01-31T00:00:00.000Z"
}]

I am calling following command to group objects by year and date:

_(data)
.groupBy(o => new Date(o.date).getFullYear() + '-' + new Date(o.date).getMonth())
.map(o1 => _(o1).map(o2 => o2.amount).sum())

Code above give me array of sums like [xx, yy, aaa, bbb, ...]

Now I need ensure that these values in array will be ordered (sum of 2018-2 will be first, and sum of 2017-1 will be on the end).

Also will be nice when result will be contains array of sorted objects as I describe above, where each object will be contains also period key "year-month" to detect what current value is. Expected output will be something like this:

[
  {period: "2018-2", amount:3000}, // sum of 2018-2
  {period: "2018-1", amount: 8000 }, // sum of 2018-1
  {period: "2017-7", amount: 3000} // sum of 2017-7
  {period: "2017-3", amount: 5000} // sum of 2017-3
  {period: "2017-1" amount: 11500} // sum of 2017-1
]

Is possible edit this chain to get required result please? Thanks!

like image 622
stack001 stack001 Avatar asked Mar 03 '26 12:03

stack001 stack001


2 Answers

You can use the function reduce along with the function Object.values

Just vanilla javascript

var data = [{   id: 1,   amount: 2000,   date: "2018-01-31T00:00:00.000Z"},{   id: 2,   amount: 3000,   date: "2017-07-31T00:00:00.000Z"},{   id: 3,   amount: 6000,   date: "2018-01-31T00:00:00.000Z"},{   id: 4,   amount: 7000,   date: "2017-01-31T00:00:00.000Z"},{   id: 5,   amount: 5000,   date: "2017-03-31T00:00:00.000Z"},{   id: 6,   amount: 3000,   date: "2018-02-22T00:00:00.000Z"},{   id: 7,   amount: 4500,   date: "2017-01-31T00:00:00.000Z"}];

var result = Object.values(data.reduce((a, c) => {
  var [year, month] = c.date.split('-');
  var key = `${year}-${+month}`;
  (a[key] || (a[key] = {period: key, amount: 0})).amount += c.amount;
  return a;
}, {})).sort((a, b) => b.period.localeCompare(a.period));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 195
Ele Avatar answered Mar 05 '26 01:03

Ele


You could get the grouped data and sort it ascending (the only possible way with lodash) and reverse the order.

var data = [{ id: 1, amount: 2000, date: "2018-01-31T00:00:00.000Z" }, { id: 2, amount: 3000, date: "2017-07-31T00:00:00.000Z" },{ id: 3, amount: 6000, date: "2018-01-31T00:00:00.000Z" }, { id: 4, amount: 7000, date: "2017-01-31T00:00:00.000Z" }, { id: 5, amount: 5000, date: "2017-03-31T00:00:00.000Z" }, { id: 6, amount: 3000, date: "2018-02-22T00:00:00.000Z" }, { id: 7, amount: 4500, date: "2017-01-31T00:00:00.000Z" }],
    result = _(data)
        .groupBy(o => o.date.slice(0, 7))
        .map((array, sort) => ({ sort, date: sort.split('-').map(Number).join('-'), amount: _.sumBy(array, 'amount') }))
        .sortBy('sort')
        .reverse()
        .map(({ date, amount }) => ({ date, amount }))
        .value();


console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
like image 39
Nina Scholz Avatar answered Mar 05 '26 02:03

Nina Scholz