使用lodash groupby的每月水平总和?
Monthly sum of level using lodash groupby?
我想使用 lodash groupby 对对象数组进行一些转换。首先应用到 2 个键 clazz_id,然后应用到月份,得到级别的总和。
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
但是,月份应用不正确。任何帮助将不胜感激。
结果应该是:
[{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'}]
您可以通过多次调用 Array.reduce()
、根据 clazz_id
和 month
.
创建分组键来获得所需的结果
然后我们将共享相同键的任何项目的 level
值相加:
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>
对于普通 Javascript,您可以使用嵌套对象进行缩减。
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; }
这可能也行。数据按一定方式排列后应用reduce。
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'),
})
})
})
console.log(data2)
var o = {}
var result = data2.reduce(function (r, e) {
var key = e.clazz_id + '|' + e.month
if (!o[key]) {
o[key] = e
r.push(o[key])
} else {
o[key].level += e.level
}
return r
}, [])
console.log(result)
}, [])
return <div className='App'>test</div>
}
export default App
我想使用 lodash groupby 对对象数组进行一些转换。首先应用到 2 个键 clazz_id,然后应用到月份,得到级别的总和。
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
但是,月份应用不正确。任何帮助将不胜感激。
结果应该是:
[{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'}]
您可以通过多次调用 Array.reduce()
、根据 clazz_id
和 month
.
然后我们将共享相同键的任何项目的 level
值相加:
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>
对于普通 Javascript,您可以使用嵌套对象进行缩减。
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; }
这可能也行。数据按一定方式排列后应用reduce。
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'),
})
})
})
console.log(data2)
var o = {}
var result = data2.reduce(function (r, e) {
var key = e.clazz_id + '|' + e.month
if (!o[key]) {
o[key] = e
r.push(o[key])
} else {
o[key].level += e.level
}
return r
}, [])
console.log(result)
}, [])
return <div className='App'>test</div>
}
export default App