d3.js - D3.js 层次结构按字段计算汇总
问题描述
请我有这样的平面json:
var data = [{ "Id": 1, "Name": "a1", "Parent": null},
{ "Id": 2, "Name": "a2", "Parent": 1},
{ "Id": 3, "Name": "a3", "Parent": 2, "nb1": 30, "nb2": 40 },
{ "Id": 4, "Name": "a4", "Parent": 2, "nb1": 25, "nb2": 64 },
{ "Id": 5, "Name": "a5", "Parent": 1},
{ "Id": 6, "Name": "a6", "Parent": 5, "nb1": 2, "nb2": 6 },
{ "Id": 7, "Name": "a7", "Parent": 5, "nb1": 5, "nb2": 4 }];
使用 d3js,我想为所有父母构建具有每个字段(nb1 和 nb2)总和的层次结构 json
我在用 :
var treeData = d3.stratify().
id(function (d) { return d.Id; })
.parentId(function (d) { returnd.Parent; })(data);
treeData.sum(d=> d.nb1)
但它返回带有总和的新字段(值)。我需要的是 nb1 的总和,并保留相同的字段名称 nb1 和 nb2 的总和,并为父母保留相同的名称字段 nb2。
或者自定义d3js层级的sum函数。非常感谢
解决方案
使用递归buildNode
函数:
const data = [
{ "Id": 1, "Name": "a1", "Parent": null},
{ "Id": 2, "Name": "a2", "Parent": 1},
{ "Id": 3, "Name": "a3", "Parent": 2, "nb1": 30, "nb2": 40 },
{ "Id": 4, "Name": "a4", "Parent": 2, "nb1": 25, "nb2": 64 },
{ "Id": 5, "Name": "a5", "Parent": 1},
{ "Id": 6, "Name": "a6", "Parent": 5, "nb1": 2, "nb2": 6 },
{ "Id": 7, "Name": "a7", "Parent": 5, "nb1": 5, "nb2": 4 }];
const getValue = (node, children, attr) =>
children.length > 0 ?
children.reduce((s, n) => s + n[attr], 0) :
node[attr];
const buildNode = (node) => {
const children = data
.filter(n => n.Parent === node.Id)
.map(n => buildNode(n));
const nb1 = getValue(node, children, 'nb1');
const nb2 = getValue(node, children, 'nb2');
return {...node, children, nb1, nb2};
}
const root = buildNode(data.find(n => !n.Parent));
console.log('ROOT: ', root)
推荐阅读
- c# - 如何在 Web Api 的主体中传递派生的 JObject 类
- django - 使用请求登录后从 Django 网站获取数据
- sql - 使用日期条件连接两个表
- mysql - MySQL插入带有来自选择的值
- doctrine-orm - 使用 QueryBuilder 制作一个依赖于多对多关系的 Doctrine 子查询
- macos - 是否有任何 MacOS SwiftUI 替代 UIKit 的 UIGraphicsBeginImageContext/UIGraphicsEndImageContext?
- javascript - 从 osutils 节点 js 返回 CPU 使用率
- c - 以这种方式包含头文件,这是一个好习惯吗?
- angular - 如何使“ng serve”与自定义 Angular 库一起使用?
- git - GitLab 管道失败:未知选项:-c