给定以下对象数组:
[{
"id": 1,
"name": "random_name1",
"published_at": "2021-01-16T08:52:24.408Z",
},
{
"id": 2,
"name": "random_name2",
"published_at": "2022-02-16T08:52:24.408Z",
},
{
"id": 3,
"name": "random_name3",
"published_at": "2020-04-16T08:52:24.408Z",
},
{
"id": 4,
"name": "random_name4",
"published_at": "2020-04-16T08:52:24.408Z",
},
{
"id": 5,
"name": "random_name5",
"published_at": "2022-05-16T08:52:24.408Z",
}
]
我需要按年和月对嵌套对象(降序)的一个数组中的项目进行分组,结果应该是:
[
{
year: '2022',
months: [
{
month: '5',
items: [
{
id: '5',
name: 'random_name5'
}
]
},
{
month: '2',
items: [
{
id: '2',
name: 'random_name2'
}
]
}
]
},
{
year: '2021',
months: [
{
month: '1',
items: [
{
id: '1',
name: 'random_name1'
}
]
},
{
month: '2',
items: [
{
id: '2',
name: 'random_name2'
}
]
}
]
},
{
year: '2020',
months: [
{
month: '4',
items: [
{
id: '3',
name: 'random_name3'
},
{
id: '4',
name: 'random_name4'
}
]
}
]
}
];
我尝试过以下方法:
items = [...new Set(items.map((item) => parseInt(item.published_at.split('-')[0])))].map((year) => [
{
year: year,
months: [
...new Set(
items
.filter((item) => parseInt(item.published_at.split('-')[0]) === year)
.map((item) => parseInt(item.published_at.split('-')[1]))
)
].map((month) => [
{
month: month,
items: items.filter(
(item) => parseInt(item.published_at.split('-')[0]) === year && parseInt(item.published_at.split('-')[1]) === month
)
}
])
}
]);
return items
上述解决方案的问题在于,它将创建一个像这样的二维数组(月份也是二维的):
[
[ { year: 2022, months: [Array] } ],
[ { year: 2021, months: [Array] } ],
[ { year: 2020, months: [Array] } ],
[ { year: 2019, months: [Array] } ],
[ { year: 2018, months: [Array] } ]
]
如何解决这个问题?
如果您获得了唯一的年月列表,您可以使用它来映射您的对象
const items = [{ "id": 1,"name": "random_name1","published_at": "2021-01-16T08:52:24.408Z", },
{ "id": 2, "name": "random_name2", "published_at": "2022-02-16T08:52:24.408Z",},
{ "id": 3, "name": "random_name3","published_at": "2020-04-16T08:52:24.408Z",},
{"id": 4, "name": "random_name4", "published_at": "2020-04-16T08:52:24.408Z",},
{ "id": 5, "name": "random_name5", "published_at": "2022-05-16T08:52:24.408Z",}]
let uniqueYearMonths = [... new Set(items.map(x => x.published_at.substring(0,7)))];
let results = [... new Set(items.map(x => x.published_at.substring(0,4)))]
.map(year => ({
year: year,
months: uniqueYearMonths
.filter(ym => ym.startsWith(year))
.map(ym => ({
month: ym.substring(5,7),
items: items
.filter(item => item.published_at.startsWith(ym))
.map(item => ({
id: item.id,
name: item.name
}))
}))
}));
console.log(results);
假设您的数组为
data
,您可以使用 map
和 reduce
等数组方法执行某些操作。
像这样:
const groupedByYear = data.map((e) => ({ ...e, published_at: new Date(e.published_at) }))
.reduce((acc, e) => {
const year = e.published_at.getFullYear();
const month = e.published_at.getMonth() + 1;
if (!acc[year]) acc[year] = { year };
if (!acc[year][month]) acc[year][month] = [];
acc[year][month] = e;
return acc;
}, {})
const result = Object.values(groupedByYear).reduce((acc, e) => {
const { year, ...months } = e;
acc.push({ year: year, months: months });
return acc;
}, [])
这是一个示例,可能不是执行此操作的最佳方法。它只是为了向您展示数据转换的路径。
首先
data.map
能够对日期进行操作。然后使用 reduce
对数据进行分组(此处使用对象)。然后从对象值创建一个数组以匹配您想要的输出。
与您展示的解决方案相比,其优点是限制了迭代数组的次数。为了获得更好的性能,避免在数组上迭代太多时间总是一个好主意。
解决这个问题的方法有很多;人们也可以考虑这种做法。我意识到我入党很晚,但希望我仍然可以通过分享想法为社区做出贡献,并通过反馈改进我的思维方式。
const items = [{ "id": 1,"name": "random_name1","published_at": "2021-01- 16T08:52:24.408Z", },
{ "id": 2, "name": "random_name2", "published_at": "2022-02-16T08:52:24.408Z",},
{ "id": 3, "name": "random_name3","published_at": "2020-04-16T08:52:24.408Z",},
{ "id": 4, "name": "random_name4","published_at": "2020-04-26T08:52:24.408Z",},
{"id": 5, "name": "random_name5", "published_at": "2020-04-21T08:52:24.408Z",},
{ "id": 6, "name": "random_name6", "published_at": "2022-05-16T08:52:24.408Z",}];
function groupYearAndMonth(items: any[], key: string) {
return [
...new Set(
items.map(item => new Date(item[key]).getFullYear().toString()) // it fetches unique years
)
].map( year => ({
year, // assign years
months: items.filter( e => new Date(e[key]).getFullYear().toString() === year) // filters months
.reduce((acc, item, index) => {
const month = (new Date(item[key]).getMonth() + 1).toString();
if (!acc[month]) {
acc[month] = [];
}
acc[month][index] = item;
return acc;
}, {} )
})
)
};
console.log(groupYearAndMonth(items, 'published_at'));