0

This question is an extention of this question here. Underscore js group by each month on each year in single level

The code which i am using is here.

        const months = [
            'January','February','March','April','May','June','July','August','September','October','November','December'
        ]
        const result = flashMessage.reduce((res:any, item:any) => {
            const date = new Date(item.created_at)
            const year = date.getFullYear();
            const month = months[date.getMonth()];
            const existingYear=res[`${month} ${year}`] ||[]; 
            const updated  = [...(existingYear[month] || []), item]
            const returnItem = {
                title:item.title,
                user_message:item.user_message,
                created_at:item.created_at
            };
            res[`${month} ${year}`] = [...existingYear,returnItem]
            return res
        }, {});

The above code is producing expected result but it is in out of order here is the result of the above code. [![enter image description here][1]][1]

I want the result is in order. The order which i wanted is shown below.

March 2022

February 2022

January 2022

March 2021

February 2021

January 2021

So on how can i do that? [1]: https://i.stack.imgur.com/BS9ZS.png

xxoyx
  • 81
  • 8
  • Extract the `keys` from the object using `Object.keys()` and then apply `.sort()` in order to obtain a new array of keys which are in an order that you desire. Next, use this array of keys to render with the correct order (in conjunction with the values from your original object). – jsN00b Mar 12 '22 at 03:15
  • @jsN00b If i use this `console.log(Object.keys(result).sort());` I am getting this output. here `[ 'February 2022', 'January 2022', 'March 2021', 'March 2022' ]` – xxoyx Mar 12 '22 at 04:04
  • Have added an answer. In order to sort, have used the actual source (ie, the `created_at` prop) directly. If `flashMessage` array may be shared - it will be helpful to provide a working demo. – jsN00b Mar 12 '22 at 08:45
  • It as same as mentioned in at this question https://stackoverflow.com/questions/70951895/underscore-js-group-by-each-month-on-each-year-in-single-level?noredirect=1#comment125428825_70951895 Mentioned in at the expected result. – xxoyx Mar 12 '22 at 17:01
  • The expected result in the other question is an `object`. If `flashMessage` is an object, then `.reduce()` may not be used. In order to use `.reduce()`, it is imperative that `flashMessage` is an array. So, once again - would you kindly share the contents of the `flashMessage` array, please. – jsN00b Mar 12 '22 at 17:13
  • 1
    It goes like this `[{ created_at: 2022-03-11T01:21:02.456Z, title: 'Announcement 02', }, { created_at: 2022-03-11T01:29:16.087Z, title: 'Announcement 25', user_message: 'see more test', }, { created_at: 2021-03-11T06:40:46.790Z, title: 'This is a push notification to all', user_message: 'A push notification to all'} ]` – xxoyx Mar 12 '22 at 17:19

1 Answers1

1

This may be one possible solution to achieve the desired objective.

// 'sortedKeys' will hold only the keys of the 'res' object
// but these will be in a sorted-order (based on prop 'created_at')
const sortedKeys = [
    ...Object.keys(result)
  ].sort(
    (a, b) => (
      result[a][0]['created_at'] > result[b][0]['created_at']
      ? -1
      : 1
    )
);

// to render in the sorted order, use 'sortedKeys' like this
sortedKeys.forEach(k => {
  console.log('key: ', k, ' value: ', result[k])
});

Approach

  • First obtain the keys from result object
  • Next, spread them and then apply .sort()
  • Sorted array is stored in sortedKeys array
  • The .sort employs the result object's created_at prop corresponding to the value of each key.
  • To validate the sort, iterate over the sortedKeys array using .forEach and display the key k and the corresponding value from result object.

Code Snippet

The below provides a working-example of the sortedKeys generated

const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const flashMessage = [
  {
    created_at: '2021-03-11T06:40:46.790Z',
    title: 'Announcement 02',
    user_message: 'see more test',
  }, {
    created_at: '2021-01-11T06:40:46.790Z',
    title: 'Announcement 25',
    user_message: 'see more test',
  }, {
    created_at: '2021-02-11T06:40:46.790Z',
    title: 'This is a push notification to all',
    user_message: 'A push notification to all'
  }, {
    created_at: '2022-01-11T06:40:46.790Z',
    title: 'title for jan 2021',
    user_message: 'message for jan 2021'
  }, {
    created_at: '2022-03-11T06:40:46.790Z',
    title: 'title for mar 2021',
    user_message: 'message for mar 2021'
  }, {
    created_at: '2022-02-11T06:40:46.790Z',
    title: 'title for feb 2021',
    user_message: 'message for feb 2021'
  }
];

const result = flashMessage.reduce((res, item) => {
  const date = new Date(item.created_at)
  const year = date.getFullYear();
  const month = months[date.getMonth()];
  const existingYear = res[`${month} ${year}`] || [];
  const updated = [...(existingYear[month] || []), item]
  const returnItem = {
    title: item.title,
    user_message: item.user_message,
    created_at: item.created_at
  };
  res[`${month} ${year}`] = [...existingYear, returnItem]
  return res
}, {});

const sortedKeys = [
  ...Object.keys(result)
].sort(
  (a, b) => (
    result[a][0]['created_at'] > result[b][0]['created_at']
    ? -1
    : 1
  )
);

console.log('keys of result object sorted: ', sortedKeys);

sortedKeys.forEach(k => {
  console.log('key: ', k, ' value: ', result[k])
});
jsN00b
  • 3,584
  • 2
  • 8
  • 21
  • THis is the output i am getting key: ` 1 February 2022 key: 0 January 2022 key: 2 March 2022 key: 2 March 2021` This one was there without this function as well. – xxoyx Mar 12 '22 at 16:49
  • but check this this is a wrong out put `1 February 2022 key: 0 January 2022 key: 2 March 2022 key: 2 March 2021` – xxoyx Mar 12 '22 at 16:50
  • Added a working-demo / code-snippet using the `flashMessage` array provided. Thanks to the array, was able to identify changes needed & once incorporated into the code-snippet - it now generates the `sortedKeys` reverse-chronological order, as indicated on the question. – jsN00b Mar 12 '22 at 17:35
  • I want to return `sortedKeys.forEach(k => { console.log('key: ', k, ' value: ', result[k]) });` inside `return Promise.resolve(result);` How can i do that? – xxoyx Mar 12 '22 at 17:44
  • The code is working as expected – xxoyx Mar 12 '22 at 17:54
  • Instead of `result`, you may return something like this: `({result, sortedKeys})`. What this does is, it will send an object with two props namely `result` and `sortedKeys`. – jsN00b Mar 12 '22 at 18:13