arrays - 将对象数组转换为对象分组数组 Typescript
问题描述
我正在尝试转换这样的对象数组:
[{grandParentField:'grandParent1', parentField:'parent1', childField: 'child1'},
{grandParentField:'grandParent1', parentField:'parent1', childField: 'child2'},
{grandParentField:'grandParent2', parentField:'parent1', childField: 'child3'},
{grandParentField:'grandParent2', parentField:'parent2', childField: 'child4'}]
变成这种形式:
[
{
text: 'grandparent1',
items: [
{
text: 'parent1',
items: [{ text: 'child1' }, { text: 'child2' }]
}
]
},
{
text: 'grandparent2',
items: [
{
text: 'parent1',
items: [{ text: 'child3' }]
},
{
text: 'parent2',
items: [{ text: 'child4' }]
}
]
}
]
这个线程与我想要的相似,但不完全是。
孩子永远是独一无二的,但父母可以有多个祖父母。
老实说,我已经尝试了很多事情,我什至不确定要包括哪一个作为最接近我的例子。
像这样的东西,但能够接收一组对象,并抽出{text: string, items:[{text: string, items:[{text:string]]}
结构:
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
console.log(groupBy(['one', 'two', 'three'], 'length'));
// => {3: ["one", "two"], 5: ["three"]}
解决方案
不要对类型太疯狂,我会说你希望你的输出是这种形状:
interface Tree {
text: string,
items?: Tree[]
}
因此,让我们创建一个名为的函数,该函数group()
将您的数组和您想要按照它们应该被处理的顺序处理的键列表。因此,对于您的示例,它将像这样使用:
const data = [
{ grandParentField: 'grandParent1', parentField: 'parent1', childField: 'child1' },
{ grandParentField: 'grandParent1', parentField: 'parent1', childField: 'child2' },
{ grandParentField: 'grandParent2', parentField: 'parent1', childField: 'child3' },
{ grandParentField: 'grandParent2', parentField: 'parent2', childField: 'child4' }
];
const groupedData = group(data, "grandParentField", "parentField", "childField");
这是 的实现group()
:
function group(data: Array<Record<string, string>>, key: string, ...otherKeys: string[]): Tree[] {
const objMap: Record<string, any[]> = {}
for (const d of data) {
if (!(d[key] in objMap)) {
objMap[d[key]] = []
}
objMap[d[key]].push(d);
}
return Object.keys(objMap).map(k => otherKeys.length ?
{
text: k,
items: group(objMap[k], otherKeys[0], ...otherKeys.slice(1))
} : {
text: k
}
);
}
首先,我们将元素 from 分组data
到一个名为 的数组字典中objMap
,其中每个元素d
进入objMap
at的键d[key]
(因此第一个元素进入名为"grandParent1"
if key
is的键"grandParentField"
)。
完成此分组后,我们通过遍历objMap
的键返回一个新数组。如果我们没有,我们只返回一个使用键作为字段的元素otherKeys
数组。如果我们确实有其他键,那么我们需要递归调用存储在正确键中的元素。{text: string}
objMap
text
group()
objMap
您可以验证这是否适用于您的示例:
console.log(JSON.stringify(groupedData, undefined, 2));
/* [
{
"text": "grandParent1",
"items": [
{
"text": "parent1",
"items": [
{
"text": "child1"
},
{
"text": "child2"
}
]
}
]
},
{
"text": "grandParent2",
"items": [
{
"text": "parent1",
"items": [
{
"text": "child3"
}
]
},
{
"text": "parent2",
"items": [
{
"text": "child4"
}
]
}
]
}
] */
推荐阅读
- html - 如何只改变
标记里面的
- 标记而无需修改 HTML
- java - HotSpot JVM可以在Java低版本模式下运行吗?
- java - 有没有办法在 Java Spring 中合并列表中不可预测的 Monos 数量?
- php - codeigniter 从文件夹中删除文件
- excel - 如何使用嵌套的 if 函数解析为“value if true”if 语句中的字符串?
- spf - 间歇性 SPF 失败,与
场地 - node.js - 使用 NestJS 和 Passport 手动启动登录会话
- javascript - 如何从不同域(express.js)上的服务器设置cookie客户端
- plsql - ORA-19202: XML 处理中发生错误 ORA-24333: 零迭代计数
- c# - Caliburn.Micro 为 ItemsControl 的 Image 添加 Click 事件