我现在正在使用power bi D3.js Visual构建客户视觉。 power bi中的D3给了我以下JSON作为输入:
var arr = [
{ "source" : "BBB", "target" : "AAA"},
{ "source" : "CCC ", "target" : "BBB"},
{ "source" : "DDDD", "target" : "AAA"},
{ "source" : "SSSS", "target" : "CCC"},
{ "source" : "EEEE", "target" : "BBB"},
{ "source" : "FFFF", "target" : "DDDD"},
但是我需要的是:
var arr =
{
"source": "AAA",
"children": [
{
"source": "BBB",
"children": [
{ "source": "CCC",
"children": [
{ "source": "SSSS"] },
{ "source": "EEEE" }
]
},
{ "source": "DDDD",
"children": [
{ "source": "FFFF" },
] },
]
}
有人可以帮忙用javascript获取这种格式吗?
我对在其他帖子上找到的以下脚本感到厌倦,已经做了一些小的更改,只是无法正常工作。
function unflatten(arr) {
var tree = [],
mappedArr = {},
arrElem,
mappedElem;
// First map the nodes of the array to an object -> create a hash table.
for(var i = 0, len = arr.length; i < len; i++) {
arrElem = arr[i];
mappedArr[arrElem.child] = arrElem;
mappedArr[arrElem.child]['children'] = [];
}
for (var id in mappedArr) {
if (mappedArr.hasOwnProperty(id)) {
console.log(mappedArr.hasOwnProperty(id))
mappedElem = mappedArr[id];
//console.log(mappedElem)
// If the element is not at the root level, add it to its parent array of children.
if (mappedElem.parent!="0") {
mappedArr[mappedElem['parent']]['children'].push(mappedElem);
}
// If the element is at the root level, add it to first level elements array.
else {
tree.push(mappedElem);
}
}
}
return tree;
}
答案 0 :(得分:0)
有很多方法可以解决此问题,这里仅是一种:
const arr = [
{ source: "BBB", target: "AAA" },
{ source: "CCC", target: "BBB" },
{ source: "DDDD", target: "AAA" },
{ source: "SSSS", target: "CCC" },
{ source: "EEEE", target: "BBB" },
{ source: "FFFF", target: "DDDD" }
];
const trunk = arr.find(x => !arr.some(y => y.source === x.target)).target;
const branches = arr.reduce((acc, x) => {
acc[x.target] = acc[x.target] || [];
acc[x.target].push(x.source);
return acc;
}, {});
const tree = buildTree(trunk, branches);
function buildTree(source, branches) {
const tree = { source };
if (branches[source]) {
tree.children = branches[source].map(x => buildTree(x, branches));
}
return tree;
}
console.log("Trunk: ", trunk);
console.log("Branches: ", branches);
console.log("Output: ", JSON.stringify(tree, null, 2));
这个想法是你:
进一步的澄清:
arr.find(x => !arr.some(y => y.source === x.target))
寻找没有父亲的分支
some()方法测试数组中至少一个元素是否通过测试。在这种情况下,由于它有一个!
,它将测试该数组中没有哪个元素具有父级。
find()方法返回没有父亲的第一个分支的值。
如果您考虑使用多个中继,则可以用find()
方法代替filter()
方法,这将返回所有中继的数组。然后,您必须像这样修改算法:
const arr = [
{ source: "BBB", target: "AAA" },
{ source: "CCC", target: "BBB" },
{ source: "DDDD", target: "AAA" },
{ source: "SSSS", target: "CCC" },
{ source: "EEEE", target: "BBB" },
{ source: "FFFF", target: "DDDD" },
{ source: "XXXX", target: "YYYY" }
];
const trunks = arr.filter(x => !arr.some(y => y.source === x.target));
const branches = arr.reduce((acc, x) => {
acc[x.target] = acc[x.target] || [];
acc[x.target].push(x.source);
return acc;
}, {});
const trees = trunks.map(x => buildTree(x.target, branches));
function buildTree(source, branches) {
const tree = { source };
if (branches[source]) {
tree.children = branches[source].map(x => buildTree(x, branches));
}
return tree;
}
console.log("Trunk: ", trunks);
console.log("Branches: ", branches);
console.log("Output: ", JSON.stringify(trees, null, 2));