我得到了一个包含多个键对象,它包含一个值数组。在这个数组中,有一个嵌套的值,我想在保留主键的同时,根据它进行分组。
所以在我的数据中我得到了:
{
"foo1": [
{
"name": "foo1",
"subpart": {
"part": "bar1"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar1"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar2"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar2"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar3"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar3"
}
}
],
"foo2": [
{
"name": "foo2",
"subpart": {
"part": "bar1"
}
},
{
"name": "foo2",
"subpart": {
"part": "bar1"
}
},
{
"name": "foo2",
"subpart": {
"part": "bar2"
}
},
{
"name": "foo2",
"subpart": {
"part": "bar3"
}
},
{
"name": "foo2",
"subpart": {
"part": "bar3"
}
}
]
}
我希望它变成:
{
"foo1": {
"bar1": [
{
"name": "foo1",
"subpart": {
"part": "bar1"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar1"
}
}
],
"bar2": [
{
"name": "foo1",
"subpart": {
"part": "bar2"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar2"
}
}
],
"bar3": [
{
"name": "foo1",
"subpart": {
"part": "bar3"
}
},
{
"name": "foo1",
"subpart": {
"part": "bar3"
}
}
]
},
"foo2": {
"bar1": [
{
"name": "foo2",
"subpart": {
"part": "bar1"
}
},
{
"name": "foo2",
"subpart": {
"part": "bar1"
}
}
],
"bar2": [
{
"name": "foo2",
"subpart": {
"part": "bar2"
}
}
],
"bar3": [
{
"name": "foo2",
"subpart": {
"part": "bar3"
}
},
{
"name": "foo2",
"subpart": {
"part": "bar3"
}
}
]
}
}
现在我已经找到了一些例子,但这只在一个级别上进行分组,其中“key”是第一个组,但我在某个子值中得到了第二个属性,作为分组的第二个级别(如果这有意义的话)。
目前为止我最好的回答是:
function groupBy<T>(arr: T[], fn: (item: T) => any) {
return arr.reduce<Record<string, T[]>>((prev, curr) => {
const groupKey = fn(curr);
const group = prev[groupKey] || [];
group.push(curr);
return { ...prev, [groupKey]: group };
}, {});
}
然后:
const grouped = groupBy(data, (x) => x.subpart.part)
但这样就把它组合成了一个主键,我不想要。
1条答案
按热度按时间fnvucqvd1#
实际上,您需要将groupByMap到数据中的每个值。
在TypeScript中Map对象有些困难/不直接。您可以先使用
Object.entries
和Object.fromEntries
将对象转换为数组,然后Map它,再将它转换回对象。但是,这样做会破坏类型推断,并使结果为any类型。因此,在需要这样做时要小心,同时还要维护类型安全。您可能也要考虑重构程式码,以便将数组架构的结构当做此转换的输入和/或输出使用,因为它更容易使用,也更容易维护类型安全。
TSPlayground