将扁平的JSON文件转换为类似于flare.json的分层JSON数据[d3示例文件]

10

在一场艰苦的斗争后,我几乎想出了如何将一个扁平的JSON文件转换为分层结构。但是我没有自己编写该函数,而是从下面的帖子中复制了它。

D3 JSON数据转换

但是现在问题是,该帖子中编写的函数只有2级分层。但是我正在寻找4级分层。我尝试重写该函数,但失败了。

以下是我尝试的代码:

var data = [
    {"dep": "第一层顶部", "name": "第一个子节点", "model": "值1", "size": "320"},
    {"dep": "第一层顶部", "name": "第一个子节点", "model": "值2", "size": "320"},
    {"dep": "第一层顶部", "name": "第一个子节点", "model": "值3", "size": "320"},
    {"dep": "第一层顶部", "name": "第一个子节点", "model": "值4", "size": "320"},
    {"dep": "第一层顶部", "name": "第二个子节点", "model": "值1", "size": "320"},
    {"dep": "第一层顶部", "name": "第二个子节点", "model": "值2", "size": "320"},
    {"dep": "第一层顶部", "name": "第二个子节点", "model": "值3", "size": "320"},
    {"dep": "第一层顶部", "name": "第二个子节点", "model": "值4", "size": "320"},
    {"dep": "第二层顶部", "name": "第一个子节点", "model": "值1", "size": "320"},
    {"dep": "第二层顶部", "name": "第一个子节点", "model": "值2", "size": "320"},
    {"dep": "第二层顶部", "name": "第一个子节点", "model": "值3", "size": "320"},
    {"dep": "第二层顶部", "name": "第一个子节点", "model": "值4", "size": "320"},
    {"dep": "第二层顶部", "name": "第二个子节点", "model": "值1", "size": "320"},
    {"dep": "第二层顶部", "name": "第二个子节点", "model": "值2", "size": "320"},
    {"dep": "第二层顶部", "name": "第二个子节点", "model": "值3", "size": "320"},
    {"dep": "第二层顶部", "name": "第二个子节点", "model": "值4", "size": "320"},
    {"dep": "第三层顶部", "name": "第一个子节点", "model": "值2", "size": "320"},
    {"dep": "第三层顶部", "name": "第一个子节点", "model": "值3", "size": "320"},
    {"dep": "第三层顶部", "name": "第一个子节点", "model": "值4", "size": "320"},
    {"dep": "第三层顶部", "name": "第一个子节点", "model": "值5", "size": "320"},
    {"dep": "第三层顶部", "name": "第二个子节点", "model": "值1", "size": "320"},
    {"dep": "第三层顶部", "name": "第二个子节点", "model": "值2", "size": "320"},
    {"dep": "第三层顶部", "name": "第二个子节点", "model": "值3", "size": "320"},
    {"dep": "第三层顶部", "name": "第二个子节点", "model": "值4", "size": "320"}
];
var newData = {"name":"根", "children":{}};
data.forEach(function(d){ if(typeof newData.children[d.dep] !== 'undefined') { newData.children[d.dep].children.push(d); } else { newData.children[d.dep] = {"name": d.dep, "children": [{"name": d.name, "children": [{"name": d.model, "size": d.size}]}]}; } });
newData.children = Object.keys(newData.children).map(function (key) { return newData.children[key]; });
// 显示结果 d3.select('body').append('pre').text(JSON.stringify(newData, null, ' '));

当前代码的输出结果

{ "name": "根目录", "children": [ { "name": "第一个顶级目录", "children": [ { "name": "第一个子目录", "children": [ { "name": "value1", "size": "320" } ] }, { "dep": "第一个顶级目录", "name": "第一个子目录", "model": "value2", "size": "320" }, { "dep": "第一个顶级目录", "name": "第一个子目录", "model": "value3", "size": "320" }, { "dep": "第一个顶级目录", "name": "第一个子目录", "model": "value4", "size": "320" }, { "dep": "第一个顶级目录", "name": "第二个子目录", "model": "value1", "size": "320" }, { "dep": "第一个顶级目录", "name": "第二个子目录", "model": "value2", "size": "320" }, { "dep": "第一个顶级目录", "name": "第二个子目录", "model": "value3", "size": "320" }, { "dep": "第一个顶级目录", "name": "第二个子目录", "model": "value4", "size": "320" } ] }, { "name": "第二个顶级目录", "children": [ { "name": "第一个子目录", "children": [ { "name": "value1", "size": "320" } ] }, { "dep": "第二个顶级目录", "name": "第一个子目录", "model": "value2", "size": "320" }, { "dep": "第二个顶级目录", "name": "第一个子目录", "model": "value3", "size": "320" }, { "dep": "第二个顶级目录", "name": "第一个子目录", "model": "value4", "size": "320" }, { "dep": "第二个顶级目录", "name": "第二个子目录", "model": "value1", "size": "320" }, { "dep": "第二个顶级目录", "name": "第二个子目录", "model": "value2", "size": "320" }, { "dep": "第二个顶级目录", "name": "第二个子目录", "model": "value3", "size": "320" }, { "dep": "第二个顶级目录", "name": "第二个子目录", "model": "value4", "size": "320" } ] }, { "name": "第三个顶级目录", "children": [ { "name": "第一个子目录", "children": [ { "name": "value2", "size": "320" } ] }, { "dep": "第三个顶级目录", "name": "第一个子目录", "model": "value3", "size": "320" }, { "dep": "第三个顶级目录", "name": "第一个子目录", "model": "value4", "size": "320" }, { "dep": "第三个顶级目录", "name": "第一个子目录", "model": "value5", "size": "320" }, { "dep": "第三个顶级目录", "name": "第二个子目录", "model": "value1", "size": "320{ "name": "根", "children": [ { "name": "第一级", "children": [ { "name": "第一个子级", "children": [ { "name": "value1", "size": "320" }, { "name": "value2", "size": "320" }, { "name": "value3", "size": "320" }, { "name": "value4", "size": "320" } ] }, { "name": "第二个子级", "children": [ { "name": "value1", "size": "320" }, { "name": "value2", "size": "320" }, { "name": "value3", "size": "320" }, { "name": "value4", "size": "320" } ] } ] }, { "name": "第二级", "children": [ { "name": "第一个子级", "children": [ { "name": "value1", "size": "320" }, { "name": "value2", "size": "320" }, { "name": "value3", "size": "320" }, { "name": "value4", "size": "320" } ] }, { "name": "第二个子级", "children": [ { "name": "value1", "size": "320" }, { "name": "value2", "size": "320" }, { "name": "value3", "size": "320" }, { "name": "value4", "size": "320" } ] } ] }, { "name": "第三级", "children": [ { "name": "第一个子级", "children": [ { "name": "value1", "size": "320" }, { "name": "value2", "size": "320" }, { "name": "value3", "size": "320" }, { "name": "value4", "size": "320" } ] }, { "name": "第二个子级", "children": [ { "name": "value1", "size": "320" }, { "name": "value2", "size": "320" }, { "name": "value3", "size": "320" }, { "name": "value4", "size": "320" } ] } ] } ] }

我已经绞尽脑汁一个星期了,但我自己无法解决它。请有人修改此函数,以便按照我已更新的分层格式获取数据。

先谢谢了!

2个回答

20

使用递归方法进行更新

这应该可以适用于 n 层,而不仅仅是2或3层。您只需要指定哪些属性定义了哪些层级。

var data = [
    { "dep": "First Top", "name": "First child", "model": "value1", "size": "320" },
    { "dep": "First Top", "name": "First child", "model": "value2", "size": "320" },
    { "dep": "First Top", "name": "SECOND CHILD", "model": "value1", "size": "320" },
    { "dep": "Second Top", "name": "First Child", "model": "value1", "size": "320" }
];

var newData = { name :"root", children : [] },
    levels = ["dep","name"];

// For each data row, loop through the expected levels traversing the output tree
data.forEach(function(d){
    // Keep this as a reference to the current level
    var depthCursor = newData.children;
    // Go down one level at a time
    levels.forEach(function( property, depth ){

        // Look to see if a branch has already been created
        var index;
        depthCursor.forEach(function(child,i){
            if ( d[property] == child.name ) index = i;
        });
        // Add a branch if it isn't there
        if ( isNaN(index) ) {
            depthCursor.push({ name : d[property], children : []});
            index = depthCursor.length - 1;
        }
        // Now reference the new child array as we go deeper into the tree
        depthCursor = depthCursor[index].children;
        // This is a leaf, so add the last element to the specified branch
        if ( depth === levels.length - 1 ) depthCursor.push({ name : d.model, size : d.size });
    });
});

嗨,Richard。感谢您的回复。但是我无法以JSON格式获取名称列。我得到了dep列值,然后是model值。在这两者之间,我需要添加名称,即dep>名称>值。我该怎么做?我不太擅长编辑函数。我尝试更改此行 - newData.children [d.dep] .children [childIndex] = {name:d.name,children [{name:d.model,size:d.size}]}; 但是无法获得它。再次感谢您的帮助。 - Unknown User
非常感谢你,Richard。在经过多天的努力后,在你的帮助下我终于做到了。再次感谢你! - Unknown User
嗨 Richard - 请帮我解决这个帖子 - Unknown User

2
var data = [
    { "state": "UP", "district": "Agra", "block": "IradatNagar","school":"APS","name":"A" },
    { "state": "UP", "district": "Agra", "block": "IradatNagar","school":"IPS","name":"B" },
    { "state": "UP", "district": "Agra", "block": "IradatNagar","school":"APS","name":"C" },
    { "state": "MP", "district": "Bhopal", "block": "chota_Bhopal","school":"DPS","name":"D" },
    { "state": "UP", "district": "Mathura", "block": "Farah","school":"HPS","name":"E" },
    { "state": "UP", "district": "Kanpur", "block": "Mania","school":"BPs","name":"F" },
    { "state": "UP", "district": "Agra", "block": "Arjun Nagar","school":"GPS","name":"G" }, 
    { "state": "MP", "district": "Gwalior", "block": "Surya Nagar","school":"DPS","name":"H" }
];

var newData = { name :"State", children : [] },
    levels = ["state","district","block","school"];

data.forEach(function(d){
    var depthCursor = newData.children;
    levels.forEach(function( property, depth )
    {
        var index;
        depthCursor.forEach(function(child,i)
        {
            if ( d[property] == child.name ) 
                index = i;
        });

        if ( isNaN(index) ) 
        {
            depthCursor.push({name : d[property], children : []});
            index = depthCursor.length - 1;
        }

        depthCursor = depthCursor[index].children;

        if ( depth === levels.length - 1 )
        {
            depthCursor.push({ name : d.name});
        }
    });
});

console.log(newData);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接