我有一个这样的对象的javascript数组:
// Id is not necessarily unique, orderly or for any specific purpose
var input = [
{ Id: 1, LongName: "Europe;Germany;Frankfurt", Attribute1: "some attribute" },
{ Id: 2, LongName: "Europe;Germany;Munich", Attribute1: "some attribute" },
{ Id: 7, LongName: "Asia;Japan;Okinawa", Attribute1: "some attribute" },
{ Id: 8, LongName: "North America;US;Seattle", Attribute1: "some attribute" },
{ Id: 10, LongName: "Asia;China;Beijing", Attribute1: "some attribute" },
{ Id: 12, LongName: "Europe;France;Paris", Attribute1: "some attribute" },
{ Id: 14, LongName: "Europe;France;Marseille", Attribute1: "some attribute" },
{ Id: 5, LongName: "Asia;Japan;Tokyo", Attribute1: "some attribute" },
{ Id: 6, LongName: "Asia;Korea;Seoul", Attribute1: "some attribute" },
{ Id: 9, LongName: "Asia;Korea;Busan", Attribute1: "some attribute" },
{ Id: 11, LongName: "North America;US;New York", Attribute1: "some attribute" },
//...
];
如何将其转换为这样的内容?
var output = [
{
Name: "Europe",
Children: [
{
Name: "Germany",
Children: [
{
Name: "Frankfurt",
Id: 1,
Attribute1: "some attribute"
},
{
Name: "Munich",
Id: 2,
Attribute1: "some attribute"
}
]
},
{
Name: "France",
Children: [
{
Name: "Paris",
Id: 12,
Attribute1: "some attribute"
},
{
Name: "Marseille",
Id: 14,
Attribute1: "some attribute"
}
]
}
],
//...
},
//...
];
我进行了一些搜索,发现了一些非常相似的主题: Transform array to object tree [JS] array of strings to tree data structure 但我想要的是嵌套数组和对象的组合,而不是上述解决方案中的对象树。
请帮帮我,谢谢!
答案 0 :(得分:1)
这是使用嵌套 reduce()
调用的解决方案。
const output = input.reduce((a, { LongName, ...attributes }) => {
const levels = LongName.split(';');
const lastLevel = levels.pop();
innerChildArray = levels.reduce((b, levelName) => {
let levelIndex = b.findIndex(({ Name }) => Name === levelName);
if (levelIndex === -1) {
levelIndex = b.push({ Name: levelName, Children: [] }) - 1;
}
return b[levelIndex].Children;
}, a);
innerChildArray.push({ Name: lastLevel, ...attributes })
return a;
}, []);
console.log(JSON.stringify(output, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script>
const input = [ { Id: 1, LongName: "Europe;Germany;Frankfurt", Attribute1: "some attribute" }, { Id: 2, LongName: "Europe;Germany;Munich", Attribute1: "some attribute" }, { Id: 7, LongName: "Asia;Japan;Okinawa", Attribute1: "some attribute" }, { Id: 8, LongName: "North America;US;Seattle", Attribute1: "some attribute" }, { Id: 10, LongName: "Asia;China;Beijing", Attribute1: "some attribute" }, { Id: 12, LongName: "Europe;France;Paris", Attribute1: "some attribute" }, { Id: 14, LongName: "Europe;France;Marseille", Attribute1: "some attribute" }, { Id: 5, LongName: "Asia;Japan;Tokyo", Attribute1: "some attribute" }, { Id: 6, LongName: "Asia;Korea;Seoul", Attribute1: "some attribute" }, { Id: 9, LongName: "Asia;Korea;Busan", Attribute1: "some attribute" }, { Id: 11, LongName: "North America;US;New York", Attribute1: "some attribute" },];
</script>
答案 1 :(得分:0)
<script>
var input = [
{ Id: 1, LongName: "Europe;Germany;Frankfurt", Attribute1: "some attribute" },
{ Id: 2, LongName: "Europe;Germany;Munich", Attribute1: "some attribute" },
{ Id: 7, LongName: "Asia;Japan;Okinawa", Attribute1: "some attribute" },
{ Id: 8, LongName: "North America;US;Seattle", Attribute1: "some attribute" },
{ Id: 10, LongName: "Asia;China;Beijing", Attribute1: "some attribute" },
{ Id: 12, LongName: "Europe;France;Paris", Attribute1: "some attribute" },
{ Id: 14, LongName: "Europe;France;Marseille", Attribute1: "some attribute" },
{ Id: 5, LongName: "Asia;Japan;Tokyo", Attribute1: "some attribute" },
{ Id: 6, LongName: "Asia;Korea;Seoul", Attribute1: "some attribute" },
{ Id: 9, LongName: "Asia;Korea;Busan", Attribute1: "some attribute" },
{ Id: 11, LongName: "North America;US;New York", Attribute1: "some attribute" }
];
let output = [];
input.forEach((item) => {
let names = item.LongName.split(';');
let records = output.filter((rec) => {
return rec.Name == names[0];
});
let rec = { Name: names[0], Children: [] };
if (records.length > 0) rec = records[0];
else output.push(rec);
let childs = rec.Children.filter((rec) => {
return rec.Name == names[1];
});
let child = { Name: names[1], Children: [] };
if (childs.length > 0) child = childs[0];
else rec.Children.push(child);
child.Children.push({ Name: names[2], Id: item.Id, Attribute1: item.Attribute1 });
});
console.log(output);
</script>
答案 2 :(得分:0)
使用forEach
循环遍历
在每个项目上,用 ;
分割名称
检查要推送的适当数组(父数组或子数组)。 (使用 ptr_arr
)
const process = (input, output = []) => {
input.forEach(({LongName, ...rest}) => {
const keys = LongName.split(";");
let ptr_arr = output;
while (keys.length > 0) {
let key = keys.shift();
if (keys.length === 0) {
// its leaf
ptr_arr.push({ Name: key, ...rest });
} else {
let index = ptr_arr.findIndex(({ Name }) => Name === key);
if (index === -1) {
ptr_arr.push({ Name: key, Children: [] });
index = ptr_arr.length - 1;
}
ptr_arr = ptr_arr[index].Children;
}
}
});
return output;
};
var input = [
{ Id: 1, LongName: "Europe;Germany;Frankfurt", Attribute1: "some attribute" },
{ Id: 2, LongName: "Europe;Germany;Munich", Attribute1: "some attribute" },
{ Id: 7, LongName: "Asia;Japan;Okinawa", Attribute1: "some attribute" },
{ Id: 8, LongName: "North America;US;Seattle", Attribute1: "some attribute" },
{ Id: 10, LongName: "Asia;China;Beijing", Attribute1: "some attribute" },
{ Id: 12, LongName: "Europe;France;Paris", Attribute1: "some attribute" },
{ Id: 14, LongName: "Europe;France;Marseille", Attribute1: "some attribute" },
{ Id: 5, LongName: "Asia;Japan;Tokyo", Attribute1: "some attribute" },
{ Id: 6, LongName: "Asia;Korea;Seoul", Attribute1: "some attribute" },
{ Id: 9, LongName: "Asia;Korea;Busan", Attribute1: "some attribute" },
{
Id: 11,
LongName: "North America;US;New York",
Attribute1: "some attribute",
},
];
console.log(process(input))
答案 3 :(得分:0)
var input = [
{ Id: 1, LongName: "Europe;Germany;Frankfurt", Attribute1: "some attribute" },
{ Id: 2, LongName: "Europe;Germany;Munich", Attribute1: "some attribute" },
{ Id: 7, LongName: "Asia;Japan;Okinawa", Attribute1: "some attribute" },
{ Id: 8, LongName: "North America;US;Seattle", Attribute1: "some attribute" },
{ Id: 10, LongName: "Asia;China;Beijing", Attribute1: "some attribute" },
{ Id: 12, LongName: "Europe;France;Paris", Attribute1: "some attribute" },
{ Id: 14, LongName: "Europe;France;Marseille", Attribute1: "some attribute" },
{ Id: 5, LongName: "Asia;Japan;Tokyo", Attribute1: "some attribute" },
{ Id: 6, LongName: "Asia;Korea;Seoul", Attribute1: "some attribute" },
{ Id: 9, LongName: "Asia;Korea;Busan", Attribute1: "some attribute" },
{ Id: 11, LongName: "North America;US;New York", Attribute1: "some attribute" },
];
output = input.reduce((result, item) =>
{
let g = item.LongName.split(';'), node1, node2, node3;
node1 = result.find ( ({Name}) => Name === g[0] ); if (node1)
node2 = node1.Children.find ( ({Name}) => Name === g[1] ); if (node2)
node3 = node2.Children.find ( ({Name}) => Name === g[2] );
if (node1 == undefined) result.push ( { Name: g[0], Children: [ { Name: g[1], Children: [ { Name: g[2], Id: item.Id, Attribute1: item.Attribute1 } ] } ] } )
else
if (node2 == undefined) node1.Children.push ( { Name: g[1], Children: [ { Name: g[2], Id: item.Id, Attribute1: item.Attribute1 } ] } )
else
if (node3 == undefined) node2.Children.push ( { Name: g[2], Id: item.Id, Attribute1: item.Attribute1 } )
else
console.log(item.LongName +' path already exists');
return result;
}, []
);
console.log(output);
答案 4 :(得分:0)
这是@pilchards 答案的扩展版本,将处理指定各种级别名称的 LongName
值的情况。
在这个例子中,ids 412 ... 415
是一个 4 级 LongName
嵌套在之前添加的 New York
叶子之下。我还更改了一些变量名称,以更好地说明它们的作用。
// Generic way
var input = [
{ Id: 1, LongName: "Europe;Germany;Frankfurt", Attribute1: "some attribute" },
{ Id: 2, LongName: "Europe;Germany;Munich", Attribute1: "some attribute" },
{ Id: 7, LongName: "Asia;Japan;Okinawa", Attribute1: "some attribute" },
{ Id: 8, LongName: "North America;US;Seattle", Attribute1: "some attribute" },
{ Id: 10, LongName: "Asia;China;Beijing", Attribute1: "some attribute" },
{ Id: 12, LongName: "Europe;France;Paris", Attribute1: "some attribute" },
{ Id: 14, LongName: "Europe;France;Marseille", Attribute1: "some attribute" },
{ Id: 5, LongName: "Asia;Japan;Tokyo", Attribute1: "some attribute" },
{ Id: 6, LongName: "Asia;Korea;Seoul", Attribute1: "some attribute" },
{ Id: 9, LongName: "Asia;Korea;Busan", Attribute1: "some attribute" },
{ Id: 11, LongName: "North America;US;New York", Attribute1: "some attribute" },
{ Id: 412, LongName: "North America;US;New York;County1", Attribute1: "some attribute" },
{ Id: 413, LongName: "North America;US;New York;County2", Attribute1: "some attribute" },
{ Id: 414, LongName: "North America;US;New York;County3", Attribute1: "some attribute" },
{ Id: 415, LongName: "North America;US;New York;County3", Attribute1: "some attribute" },
];
output = input.reduce((rootChildren, { LongName, ...attributes }) => {
const levelnames = LongName.split(';');
const leafname = levelnames.pop();
// descend the tree to the array containing the leafs. insert levels as needed
const bottomChildren = levelnames.reduce( (children, levelName) => {
let levelIndex = children.findIndex ( ({Name}) => Name === levelName);
if (levelIndex === -1) { // add new level at end of children
levelIndex = children.push ({ Name: levelName, Children:[] }) - 1;
} else
if (!children[levelIndex].hasOwnProperty("Children")) { // add Children to existing node
children[levelIndex].Children = [];
}
return children[levelIndex].Children; // descend
}, rootChildren);
// add the leaf
bottomChildren.push({ Name: leafname, ...attributes });
return rootChildren;
}, []);
console.log(JSON.stringify(output,null,2));