1

我正在尝试构建一个基于父子关系划分数据的 D3 可视化。
http://blog.luzid.com/2013/extending-the-d3-zoomable-sunburst-with-labels/ 这些示例中使用的 JSON 遵循与此类似的模式:

var flare = {
    "name": "family",
    "size": 2000,
    "children": [{
        "name": "kidWithoutKids",
        "size": 100
    }, {
        "name": "kidWithKids",
        "size": 1900,
        "children": [{
            "name": "grandkidWithoutKids",
            "size": 100
        }, {
            "name": "grandkidWithKids",
            "size": 1900,
            "children": [...and so on...]
        }]
    }]
}

我需要做的是获取一组表格数据并将其转换为该格式的 JSON 对象。因此,我输入的数据(我无法更改)如下所示:

var arrayChildParent = [
    [{"thisText":"family"},{"thisText":"-"},{"thisNum":2000}],
    [{"thisText":"kidWithoutKids"},{"thisText":"family"},{"thisNum":100}],
    [{"thisText":"kidWithKids"},{"thisText":"family"},{"thisNum":1900}],
    [{"thisText":"grandkidWithoutKids"},{"thisText":"kidWithKids"},{"thisNum":100}],
    [{"thisText":"grandkidWithKids"},{"thisText":"kidWithKids"},{"thisNum":1800}],
  ..... and so on
]

所以,你可以把它想象成一张有 Child | 的桌子。家长 | 尺寸。显然,拥有一个像这样工作的函数会很棒:

var flare = createJSON(arrayChildParent);

数据可以按任何顺序出现,所以我一直很难构建一个循环遍历数据并创建 JSON 树的递归函数,但有时我可能有一个孩子,其父级的父级尚未创建. 我还尝试先循环创建父母或父母与父母的索引,但管理起来非常困难。

现在,我想知道我是不是走错了路。有没有更简单的方法可以简单地将我拥有的阵列数据集加载到 D3 中以用于树结构?

任何帮助将不胜感激。谢谢!

4

1 回答 1

1

这是您可以完成此任务的一种方法。

第一步是稍微清理一下数据,这样它就足够明智了。您可以Array.map()用来遍历数据并使每个数据成为对象:

var cleanData = arrayChildParent.map(function(d) {
  return {
    name: d[0].thisText,
    parent: d[1].thisText,
    size: d[2].thisNum
  };
});

然后你需要一个函数来找到所有parent给定的数据点name,然后递归地找到他们的孩子。这很容易通过结合使用来Array.filter()完成Array.map()

function getChildren(name) {
  return cleanData.filter(function(d) { return d.parent === name; })
    .map(function(d) {
      return {
        name: d.name,
        size: d.size,
        children: getChildren(d.name)
      };
    })
}

然后,您的flare变量只是调用的第一个getChildren结果-

var flare = getChildren('-')[0];

编辑:

或者,格式化为您在问题中提到的单个函数:

var flare = createJSON(arrayChildParent);

function createJSON(yuckyData) {

  var happyData = yuckyData.map(function(d) {
    return {
      name: d[0].thisText,
      parent: d[1].thisText,
      size: d[2].thisNum
    };
  });

  function getChildren(name) {
    return happyData.filter(function(d) { return d.parent === name; })
      .map(function(d) {
        return {
          name: d.name,
          size: d.size,
          children: getChildren(d.name)
        };
      });
  }

  return getChildren('-')[0];
}
于 2014-08-19T22:38:29.113 回答