I have like to make some conversions using lodash groupby to an array of objects. Applying to 2 keys clazz_id first and then month resulting in the sum of the level.
import './App.css'
import _ from 'lodash'
import { useEffect } from 'react'
import moment from 'moment'
import groupBy from 'lodash/groupBy'
const data1 = [
{
id: 1,
clazz_id: 1,
answers: [
{ level: 8, created_at: '2022-01-19T09:13:42.149 08:00' },
{ level: 1, created_at: '2022-02-19T09:13:42.149 08:00' },
],
},
{
id: 2,
clazz_id: 2,
answers: [
{ level: 7, created_at: '2022-01-19T09:13:42.149 08:00' },
{ level: 2, created_at: '2022-03-19T09:13:42.149 08:00' },
],
},
{
id: 3,
clazz_id: 2,
answers: [
{ level: 3, created_at: '2022-01-19T09:13:42.149 08:00' },
{ level: 8, created_at: '2022-02-19T09:13:42.149 08:00' },
],
},
]
const App = () => {
const data2 = []
useEffect(() => {
data1.map((item) => {
item.answers.map((e) => {
data2.push({
clazz_id: item.clazz_id,
level: e.level,
month: moment(e.created_at).format('MMM'),
})
})
})
const a = groupBy(data2, 'clazz_id', 'month')
console.log(a)
}, [])
return <div className='App'>test</div>
}
export default App
However, the month was not applied correctly. Any help would be greatly appreciated.
The result should be:
[{clazz_id: 1, level: 8, month: 'Jan'},
{clazz_id: 1, level: 1, month: 'Feb'}]
[{clazz_id: 2, level: 10, month: 'Jan'},
{clazz_id: 2, level: 8, month: 'Feb'},
{clazz_id: 2, level: 2, month: 'Mar'}]
CodePudding user response:
You could get the required result using a couple of calls to Array.reduce()
, creating a grouping key based on clazz_id
and month
.
We then sum the level
value for any items that shar the same key:
const data1 = [ { id: 1, clazz_id: 1, answers: [ { level: 8, created_at: '2022-01-19T09:13:42.149 08:00' }, { level: 1, created_at: '2022-02-19T09:13:42.149 08:00' }, ], }, { id: 2, clazz_id: 2, answers: [ { level: 7, created_at: '2022-01-19T09:13:42.149 08:00' }, { level: 2, created_at: '2022-03-19T09:13:42.149 08:00' }, ], }, { id: 3, clazz_id: 2, answers: [ { level: 3, created_at: '2022-01-19T09:13:42.149 08:00' }, { level: 8, created_at: '2022-02-19T09:13:42.149 08:00' }, ], }, ]
const result = Object.values(data1.reduce((acc, { clazz_id, answers }) => {
return answers.reduce((acc, { level, created_at }) => {
const month = moment(created_at).format('MMM');
const key = `${clazz_id}-${month}`;
acc[key] = acc[key] || { clazz_id, level: 0, month };
acc[key].level = level
return acc;
}, acc);
}, {}));
console.log('Result:')
result.forEach(r => console.log(JSON.stringify(r)))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8 M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
CodePudding user response:
With plain Javascript, you could reduce with a nested object.
const
data = [{ id: 1, clazz_id: 1, answers: [{ level: 8, created_at: '2022-01-19T09:13:42.149 08:00' }, { level: 1, created_at: '2022-02-19T09:13:42.149 08:00' }] }, { id: 2, clazz_id: 2, answers: [{ level: 7, created_at: '2022-01-19T09:13:42.149 08:00' }, { level: 2, created_at: '2022-03-19T09:13:42.149 08:00' }] }, { id: 3, clazz_id: 2, answers: [{ level: 3, created_at: '2022-01-19T09:13:42.149 08:00' }, { level: 8, created_at: '2022-02-19T09:13:42.149 08:00' }] }],
result = Object
.values(data.reduce((r, { clazz_id, answers }) => {
r[clazz_id] ??= {};
answers.forEach(({ level, created_at }) => {
const
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
monthV = new Date(created_at).getMonth(),
month = months[monthV];
r[clazz_id][monthV] ??= { clazz_id, level: 0, month };
r[clazz_id][monthV].level = level;
});
return r;
}, {}))
.map(Object.values);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }