javascript - 在 javascript 中给定路径和元素数组构建自定义对象
问题描述
本质上,我想在给定对象数组的情况下构建一个新结构。对象有效负载看起来像下面的元素数组。
const data = [
{
path: [],
elements: ['Parent A']
},
{
path: ['Parent A'],
elements: ['Child A1', 'Child A2', 'Parent B']
},
{
path: ['Parent A', 'Parent B'],
elements: ['Child B1', 'Parent C']
},
{
path: ['Parent A', 'Parent B', 'Parent C'],
elements: ['Child C1']
},
{
path: ['Parent D'],
elements: ['Child D1']
},
]
然后,上面的有效负载将被转换为如下所示的自定义对象。
let newObject =
[
{
elem: "",
children: [
{
elem: "Parent A",
children: [
{
elem: "Child A1",
children: []
},
{
elem: "Child A2",
children: []
},
{
elem: "Parent B",
children: [
{
elem: "Child B1",
children: []
},
{
elem: "Parent C",
children: [
{
elem: "Child C1",
children: []
}
]
},
]
},
]
}
]
},
{
elem: "Parent D",
children: [
{
elem: "Child D1",
children: []
}
]
}
]
我考虑过制作一个地图,其中我为每个元素提供了一个访问过的属性(以避免重新创建一个元素)并使用递归方法来填充潜在的父级。但是,我目前陷入困境,正在寻找关于我应该使用什么数据结构/方法的反馈。
我的映射器代码
const stringifyPath = (arr) => {
return arr.join('>');
}
let elemMap = new Map();
data.forEach(item => {
const itemPath = stringifyPath(item.path);
if (!elemMap.get(itemPath)) {
elemMap.set(itemPath, {
elements: [],
visited: false
})
}
elemMap.get(itemPath).elements = [...elemMap.get(itemPath).elements, ...item.elements];
});
这产生
{
'' => { elements: [ 'Parent A' ], visited: false },
'Parent A' => { elements: [ 'Child A1', 'Child A2', 'Parent B' ],
visited: false },
'Parent A>Parent B' => { elements: [ 'Child B1', 'Parent C' ], visited: false },
'Parent A>Parent B>Parent C' => { elements: [ 'Child C1' ], visited: false },
'Parent D' => { elements: [ 'Child D1' ], visited: false } }
任何反馈表示赞赏,谢谢!
解决方案
您可以通过减少为每个嵌套级别查找对象的路径并将新元素推送到找到的对象的子项来采用直截了当的方法。
对我来说,存储所有路径是没有意义的,因为构建结构只需要它们一次。
var data = [{ path: [], elements: ['Parent A'] }, { path: ['Parent A'], elements: ['Child A1', 'Child A2', 'Parent B'] }, { path: ['Parent A', 'Parent B'], elements: ['Child B1', 'Parent C'] }, { path: ['Parent A', 'Parent B', 'Parent C'], elements: ['Child C1'] }, { path: ['Parent D'], elements: ['Child D1'] }],
result = data.reduce((r, { path, elements }) => {
path
.reduce((array, elem) => {
var temp = array.find(q => q.elem === elem);
if (!temp) array.push(temp = { elem, children: [] });
return temp.children;
}, r)
.push(...elements.map(elem => ({ elem, children: [] })));
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
推荐阅读
- r - 有没有办法在 purrr/lapply 中自我识别列表元素的名称?
- dart - 如何向 In Flutter Web 发出 HTTP 请求
- celery - 芹菜工人 onStart 事件?
- html - 如果按钮被聚焦,如何为元素提供一些属性
- git - 如何在不合并的情况下使用来自 2 个 git 分支的组合文件?
- jquery - 对于已定义类的元素,classList 未定义
- python - @unique 装饰器在 python 中做了什么?
- php - 如何使用 PHP 从 Youtube API 获取标签长度
- html - 此表可访问性是否安全
- css - 动画 SVG 路径的 stroke-dashoffset 导致 Safari 中的性能极度下降