我在csv中有分层数据:不同的级别用分号分隔,值用逗号分隔(在"行"的末尾):
Parent1;Child1;Grandchild1;3;3,5
Parent1;Child1;Grandchild2;3;3,5
Parent2;Child2;Grandchild2;4,4
Parent3;Child4;Grandchild1;5,5
我希望使用javascript / jQuery / d3.js将其转换为多维数组,如下所示:
var tree = [
{
text: "Parent 1",
nodes: [
{
text: "Child 1",
nodes: [
{
text: "Grandchild 1"
},
{
text: "Grandchild 2"
}
]
},
{
text: "Child 2"
}
]
},
{
text: "Parent 2"
},
{
text: "Parent 3"
},
{
text: "Parent 4"
},
{
text: "Parent 5"
}
];
困难似乎是我需要递归循环并小心数组的深度(我不希望该值成为我的多维数组的一部分)。
目前我的代码看起来像这样,但它无法正常工作:
function createNavi(jsonRoot){
function printParentAddChildren(parent){
var parentObj = {};
parentObj.text = parent.name;
parentObj.backColor = colors[parent.depth];
var children = parent.children;//array of objects(children)
if(children==null)return parentObj;
parentObj.node = [];
for(var i=0;i<children.length;i++){
parentObj.node.push(printParentAddChildren(children[i]));
}
return parentObj;
}
var tree = [];
var children = jsonRoot.children; //array of objects(children)
for(var i=0;i<children.length;i++){
tree.push(printParentAddChildren(children[i]));
}
$('#tree').treeview({
data: tree
});
console.log(tree);
};
我想对你们这些人来说很容易! 提前感谢您的努力!
答案 0 :(得分:2)
这正是d3.nest
的意思。
给定文件 test.csv ,如:
p;c;g;r1;r2
Parent1;Child1;Grandchild1;3;3,5
Parent1;Child1;Grandchild2;3;3,5
Parent2;Child2;Grandchild2;4,4
Parent3;Child4;Grandchild1;5,5
此:
var dsv = d3.dsv(";", "text/plain");
dsv("test.csv", function(data){
var n = d3.nest()
.key(function(d){ return d.p })
.key(function(d){ return d.c })
.key(function(d){ return d.g })
.entries(data);
});
生成n为:
[{
"key": "Parent1",
"values": [{
"key": "Child1",
"values": [{
"key": "Grandchild1",
"values": [{
"p": "Parent1",
"c": "Child1",
"g": "Grandchild1",
"r1": "3",
"r2": "3,5"
}]
}, {
"key": "Grandchild2",
"values": [{
"p": "Parent1",
"c": "Child1",
"g": "Grandchild2",
"r1": "3",
"r2": "3,5"
}]
}]
}]
}, {
"key": "Parent2",
"values": [{
"key": "Child2",
"values": [{
"key": "Grandchild2",
"values": [{
"p": "Parent2",
"c": "Child2",
"g": "Grandchild2",
"r1": "4,4"
}]
}]
}]
}, {
"key": "Parent3",
"values": [{
"key": "Child4",
"values": [{
"key": "Grandchild1",
"values": [{
"p": "Parent3",
"c": "Child4",
"g": "Grandchild1",
"r1": "5,5"
}]
}]
}]
}]
工作代码here。
评论的编辑
var dsv = d3.dsv(";", "text/plain");
dsv("test.csv", function(data){
var n = d3.nest()
.key(function(d){ return d.p })
.key(function(d){ return d.c })
.rollup(function(d){
return d.map(function(d1){
return {key: d1.g};
})
})
.entries(data);
function renameKeys(obj){
obj.forEach(function(d){
d.text = d.key;
delete d.key;
if (d.values){
d.nodes = d.values;
delete d.values;
renameKeys(d.nodes);
}
});
}
renameKeys(n);
});
产地:
[{
"text": "Parent1",
"nodes": [{
"text": "Child1",
"nodes": [{
"text": "Grandchild1"
}, {
"text": "Grandchild2"
}]
}]
}, {
"text": "Parent2",
"nodes": [{
"text": "Child2",
"nodes": [{
"text": "Grandchild2"
}]
}]
}, {
"text": "Parent3",
"nodes": [{
"text": "Child4",
"nodes": [{
"text": "Grandchild1"
}]
}]
}]
更新了code。
答案 1 :(得分:0)
嗯,我想这就像纯JS一样。如你所见,它不是很多代码,而是一个复杂的代码。让我先展示代码,然后我将介绍它。
var csv = "Parent1;Child1;Grandchild1;3;3,5\nParent1;Child1;Grandchild2;3;3,5\nParent2;Child2;Grandchild2;4,4\nParent3;Child4;Grandchild1;5,5";
function construct(csv){
var arr = csv.split("\n").map(e => e.match(/[A-Za-z]+\d*/g));
function nest(a,p){
var fi = p.findIndex(e => e.text == a[0]);
~fi ? "nodes" in p[fi] ? nest(a.slice(1),p[fi].nodes)
: a.length > 1 && (p[fi].nodes = nest(a.slice(1),[]))
: (p.push({"text": a[0]}),
nest(a,p));
return p;
}
return arr.reduce((p,c) => {p = nest(c,p); return p},[]);
}
document.write("<pre>" + JSON.stringify(construct(csv), null, 2) + "</pre>")
&#13;
确定construct
函数接受csv文本,首先将事物转换为数组数组,将每行中的每个单词保存为
[ [ 'Parent1', 'Child1', 'Grandchild1' ],
[ 'Parent1', 'Child1', 'Grandchild2' ],
[ 'Parent2', 'Child2', 'Grandchild2' ],
[ 'Parent3', 'Child4', 'Grandchild1' ] ]
construct
函数负责构造具有父对象作为项的最外层数组。它通过使用具有空数组初始值的Array.prototype.reduce()
实现来完成这项工作。 nest
函数递归地处理内部数组元素,它就是所有blackmagic发生的地方。