以特定格式重新排列 Javascript 数组
Re-arrange a Javascript array in a specific format
请注意这不是重复的问题。
我很难找到从这个 JSON 数组开始的方法,
这是一级数组,我们可以在 "path" 属性
中获得每个对象或元素的路径
[
{
"name" : "a-1",
"path" : "a-1",
"parent": ""
},
{
"name" : "a-2",
"path" : "a-1>a-2",
"parent": "a-1"
},
{
"name" : "a-3",
"path" : "a-1>a-2>a-3",
"parent": "a-2"
},
{
"name" : "a-4",
"path" : "a-1>a-4",
"parent": "a-1"
},
{
"name" : "b-1",
"path" : "b-1",
"parent": ""
}
]
最后的结果应该是这样的,
[
{
"attr": {
"name": "a-1",
"path": "a-1",
"parent": ""
},
"children": [
{
"attr": {
"name": "a-2",
"path": "a-1>a-2",
"parent": "a-1"
},
"children": [
{
"attr": {
"name": "a-3",
"path": "a-1>a-2>a-3",
"parent": "a-2"
}
}
]
},
{
"attr": {
"name": "a-4",
"path": "a-1>a-4",
"parent": "a-1"
}
}
]
},
{
"attr": {
"name": "b-1",
"path": "b-1",
"parent": ""
}
}
]
我尝试将父级与过滤器和查找功能一起使用
theOneLevelArray.filter((elt, idx, arr) => {
let parent = arr.find(e => e.componentItemNumber === elt.parentItemNumber);
if (!parent) return true;
(parent.children = parent.children || []).push(elt);
});
我也尝试过使用循环,然后在 'split(">")' 路径元素之后应用 reduce 函数(这种方法的代码真的很乱,这就是我没有粘贴的原因)
要使用给定路径,您可以通过检查给定 path
和临时结果来采用迭代方法。
这需要有序的数据。
var data = [{ name: "a-1", path: "a-1", parent: "" }, { name: "a-2", path: "a-1>a-2", parent: "a-1" }, { name: "a-3", path: "a-1>a-2>a-3", parent: "a-2" }, { name: "a-4", path: "a-1>a-4", parent: "a-1" }, { name: "b-1", path: "b-1", parent: "" }],
tree = [];
data.forEach(function (object) {
object.path.split('>').reduce(function (level, key) {
var temp = level.find(({ attr: { name } }) => key === name);
if (!temp) {
temp = { attr: object, children: [] };
level.push(temp);
}
return temp.children;
}, tree);
});
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
另一种方法是使用 parent
属性 和一个临时对象作为对同名对象的引用。
这也适用于未排序的数据。
var data = [{ name: "a-1", path: "a-1", parent: "" }, { name: "a-2", path: "a-1>a-2", parent: "a-1" }, { name: "a-3", path: "a-1>a-2>a-3", parent: "a-2" }, { name: "a-4", path: "a-1>a-4", parent: "a-1" }, { name: "b-1", path: "b-1", parent: "" }],
tree = function (data, root) {
var r = [], o = {};
data.forEach(function (attr) {
var temp = { attr };
if (o[attr.name] && o[attr.name].children) {
temp.children = o[attr.name] && o[attr.name].children;
}
o[attr.name] = temp;
if (attr.parent === root) {
r.push(temp);
} else {
o[attr.parent] = o[attr.parent] || {};
o[attr.parent].children = o[attr.parent].children || [];
o[attr.parent].children.push(temp);
}
});
return r;
}(data, '');
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
简单的递归方法:
function getNodes(parentName) {
const mapNode = (node) => {
const children = getNodes(node.name);
return children.length > 0 ?
{ attr: node, children } :
{ attr: node };
};
return source
.filter(n => n.parent === parentName)
.map(mapNode);
}
调用:getNodes('')
假定source
为原数组
请注意这不是重复的问题。
我很难找到从这个 JSON 数组开始的方法, 这是一级数组,我们可以在 "path" 属性
中获得每个对象或元素的路径[
{
"name" : "a-1",
"path" : "a-1",
"parent": ""
},
{
"name" : "a-2",
"path" : "a-1>a-2",
"parent": "a-1"
},
{
"name" : "a-3",
"path" : "a-1>a-2>a-3",
"parent": "a-2"
},
{
"name" : "a-4",
"path" : "a-1>a-4",
"parent": "a-1"
},
{
"name" : "b-1",
"path" : "b-1",
"parent": ""
}
]
最后的结果应该是这样的,
[
{
"attr": {
"name": "a-1",
"path": "a-1",
"parent": ""
},
"children": [
{
"attr": {
"name": "a-2",
"path": "a-1>a-2",
"parent": "a-1"
},
"children": [
{
"attr": {
"name": "a-3",
"path": "a-1>a-2>a-3",
"parent": "a-2"
}
}
]
},
{
"attr": {
"name": "a-4",
"path": "a-1>a-4",
"parent": "a-1"
}
}
]
},
{
"attr": {
"name": "b-1",
"path": "b-1",
"parent": ""
}
}
]
我尝试将父级与过滤器和查找功能一起使用
theOneLevelArray.filter((elt, idx, arr) => {
let parent = arr.find(e => e.componentItemNumber === elt.parentItemNumber);
if (!parent) return true;
(parent.children = parent.children || []).push(elt);
});
我也尝试过使用循环,然后在 'split(">")' 路径元素之后应用 reduce 函数(这种方法的代码真的很乱,这就是我没有粘贴的原因)
要使用给定路径,您可以通过检查给定 path
和临时结果来采用迭代方法。
这需要有序的数据。
var data = [{ name: "a-1", path: "a-1", parent: "" }, { name: "a-2", path: "a-1>a-2", parent: "a-1" }, { name: "a-3", path: "a-1>a-2>a-3", parent: "a-2" }, { name: "a-4", path: "a-1>a-4", parent: "a-1" }, { name: "b-1", path: "b-1", parent: "" }],
tree = [];
data.forEach(function (object) {
object.path.split('>').reduce(function (level, key) {
var temp = level.find(({ attr: { name } }) => key === name);
if (!temp) {
temp = { attr: object, children: [] };
level.push(temp);
}
return temp.children;
}, tree);
});
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
另一种方法是使用 parent
属性 和一个临时对象作为对同名对象的引用。
这也适用于未排序的数据。
var data = [{ name: "a-1", path: "a-1", parent: "" }, { name: "a-2", path: "a-1>a-2", parent: "a-1" }, { name: "a-3", path: "a-1>a-2>a-3", parent: "a-2" }, { name: "a-4", path: "a-1>a-4", parent: "a-1" }, { name: "b-1", path: "b-1", parent: "" }],
tree = function (data, root) {
var r = [], o = {};
data.forEach(function (attr) {
var temp = { attr };
if (o[attr.name] && o[attr.name].children) {
temp.children = o[attr.name] && o[attr.name].children;
}
o[attr.name] = temp;
if (attr.parent === root) {
r.push(temp);
} else {
o[attr.parent] = o[attr.parent] || {};
o[attr.parent].children = o[attr.parent].children || [];
o[attr.parent].children.push(temp);
}
});
return r;
}(data, '');
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
简单的递归方法:
function getNodes(parentName) {
const mapNode = (node) => {
const children = getNodes(node.name);
return children.length > 0 ?
{ attr: node, children } :
{ attr: node };
};
return source
.filter(n => n.parent === parentName)
.map(mapNode);
}
调用:getNodes('')
假定source
为原数组