我有一个嵌套的 JSON 结构数组,它们的深度各不相同,而且各处的键集都不相同:
[
{
"name":"bob",
"salary":10000,
"friends":[
{
"name": "sarah",
"salary":10000
},
{
"name": "bill",
"salary":5000
}
]
},
{
"name":"marge",
"salary":10000,
"friends":[
{
"name": "rhonda",
"salary":10000
},
{
"name": "mike",
"salary":5000,
"hobbies":[
{
"name":"surfing",
"frequency":10
},
{
"name":"surfing",
"frequency":15
}
]
}
]
},
{
"name":"joe",
"salary":10000,
"friends":[
{
"name": "harry",
"salary":10000
},
{
"name": "sally",
"salary":5000
}
]
}
]
我想使用 D3 将其呈现为嵌套的 html 表格。例如, friend 列将有表格显示行中引用的个人 friend 的姓名和薪水。有时其中一个表会有另一层的子表。
我想这样做的方法是递归地创建表。我写了一个 python 程序,它采用这样的 JSON 结构,并在表中呈现表,最简单的方法是递归。我在 d3.js 文档中看到有一个可以调用的 .each()
东西,我确信这是我需要的,我只需要一点点提升就可以到达那里 ( https://github.com/mbostock/d3/wiki/Selections#wiki-each )。
那么在 D3 中是否有一个很好的方法来做到这一点?我发现了这个将二维数据矩阵渲染为表格的好例子 Creating a table linked to a csv file .通过该教程,我能够将这个数据结构的最外层呈现为表格,但我仍然坚持如何根据需要递归地进入各个层次,截至目前,它们只是在表格中显示为“对象”因为我没有将它们与普通字符串和数字区别对待。
我还发现了与我的问题类似的其他问题/答案,但我真的不太了解 javascript,无法了解递归发生的位置/方式并重新调整解决方案以满足我的需求:How do I process data that is nested multiple levels in D3? .非常感谢任何有关递归或迭代处理嵌套树(如 D3 中的 JSON 数据结构)的教程的建议或指针!
最佳答案
递归函数可能是个不错的方法。请参阅下面的代码以了解一种可能的实现方式(假设您的数据存储在 jdata
中)。请参阅代码中的注释以获得一些解释,并查看此要点以获得实时版本:http://bl.ocks.org/4085017
d3.select("body").selectAll("table")
.data([jdata])
.enter().append("table")
.call(recurse);
function recurse(sel) {
// sel is a d3.selection of one or more empty tables
sel.each(function(d) {
// d is an array of objects
var colnames,
tds,
table = d3.select(this);
// obtain column names by gathering unique key names in all 1st level objects
// following method emulates a set by using the keys of a d3.map()
colnames = d // array of objects
.reduce(function(p,c) { return p.concat(d3.keys(c)); }, []) // array with all keynames
.reduce(function(p,c) { return (p.set(c,0), p); }, d3.map()) // map with unique keynames as keys
.keys(); // array with unique keynames (arb. order)
// colnames array is in arbitrary order
// sort colnames here if required
// create header row using standard 1D data join and enter()
table.append("thead").append("tr").selectAll("th")
.data(colnames)
.enter().append("th")
.text(function(d) { return d; });
// create the table cells by using nested 2D data join and enter()
// see also http://bost.ocks.org/mike/nest/
tds = table.append("tbody").selectAll("tr")
.data(d) // each row gets one object
.enter().append("tr").selectAll("td")
.data(function(d) { // each cell gets one value
return colnames.map(function(k) { // for each colname (i.e. key) find the corresponding value
return d[k] || ""; // use empty string if key doesn't exist for that object
});
})
.enter().append("td");
// cell contents depends on the data bound to the cell
// fill with text if data is not an Array
tds.filter(function(d) { return !(d instanceof Array); })
.text(function(d) { return d; });
// fill with a new table if data is an Array
tds.filter(function(d) { return (d instanceof Array); })
.append("table")
.call(recurse);
});
}
关于javascript - 递归地(或迭代地)用 d3.js 制作一个嵌套的 html 表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13337402/