【问题标题】:d3js roll up a nested JSON array and sum up a total valued3js 汇总一个嵌套的 JSON 数组并求和一个总值
【发布时间】:2017-02-01 16:52:41
【问题描述】:

我有这个 JSON

[{
    "month": "september",
    "detail": [{
        "date": "01-09",
        "value": 5
    }, {
        "date": "02-09",
        "value": 5
    }, {
        "date": "03-09",
        "value": 5
    }, {
        "date": "04-09",
        "value": 5
    }, {
        "date": "05-09",
        "value": 5
    }, {
        "date": "06-09",
        "value": 5
    }, {
        "date": "07-09",
        "value": 0
    }]
},

{
    "month": "october",
    "detail": [{
        "date": "01-10",
        "value": 10
    }, {
        "date": "02-10",
        "value": 5
    }, {
        "date": "03-10",
        "value": 5
    }, {
        "date": "04-10",
        "value": 5
    }, {
        "date": "05-10",
        "value": 5
    }, {
        "date": "07-10",
        "value": 10
    }]
}

我想使用 d3nest 为每个特定月份汇总对象“详细信息”中的所有“值”。如果您计算每个特定月份的所有值,它将导致:september-value: 30 & october-value: 40。

我尝试过嵌套它,但无法正确总结每个月的值。查看我的代码。

d3.json('runningdata.json', function (error, data) {
console.log(data);

var Total = d3.nest()
.key(function(d) { return d.month; })
.rollup(function(value) { return d3.sum(value, function(v) { return v.detail.value; }); })

.entries(data);
console.log(JSON.stringify(Total));
});

以上所有这些都会导致:

[{"key":"september","values":0},{"key":"october","values":0}]

您可以注意到“键”工作正常,它们以月份为值。但是“值”字段的结果为 0。我想要实现的目标是:

[{"key":"september","values":30},{"key":"october","values":40}]

但是当我尝试这个时:

.rollup(function(value) { return d3.sum(value, function(v) { return v.detail[0].value; }); })

代替:

.rollup(function(value) { return d3.sum(value, function(v) { return v.detail.value; }); })

它显示了数组中第一个对象的值。

[{"key":"september","values":5},{"key":"october","values":10}]

我做错了什么?我一直在阅读有关 d3 嵌套的信息。 欢迎任何帮助。

注意: 我试图实现这一点,以制作一个显示每个月总数的图表,当您单击特定月份时,它将以天为单位查看其月份的详细信息。

【问题讨论】:

  • 您可以只使用基本的.reduce() 函数。我会发布解决方案
  • 查看我的更新解决方案

标签: javascript arrays json d3.js


【解决方案1】:

你必须像这样更新你的 d3.sum 函数:

d3.sum(value[0].detail, function(v) {
   return v.value;
});

所以你的整个代码是:

var Total = d3.nest()
.key(function(d) {
    return d.month;
})
.rollup(function(value) {
    return d3.sum(value[0].detail, function(v) {
        return v.value;
    });
})
.entries(data);

【讨论】:

  • 你能解释一下为什么 value[0].detail;工作和细节[0];值没用?
  • 因为 value 是一个数组而不是一个对象。它是一个对象数组,其中包含再次作为数组的详细信息。因此我们将 value[0].detail 传递给 d3.sum 方法
  • 所以在这种情况下使用函数 d3.sum,然后在数组对象“detail”中定义值 [0] 的数组。之后寻找定义为“v.value;”的值
【解决方案2】:

您可以使用基本的 javascript .reduce() 函数来解决问题。这会将您的对象结构数组汇总为单个对象,其中月份作为属性名称,值的总和作为值。这样做的好处是,如果您想获得 9 月份的总数,您可以简单地说 combined.september,而不必遍历数组,使用 @987654323 搜索对象@property 等于“september”,然后提取值。但是,如果您需要保留原始结构,请参阅我的答案底部的稍作修改的版本。

var data = [{
    "month": "september",
    "detail": [{
        "date": "01-09",
        "value": 5
    }, {
        "date": "02-09",
        "value": 5
    }, {
        "date": "03-09",
        "value": 5
    }, {
        "date": "04-09",
        "value": 5
    }, {
        "date": "05-09",
        "value": 5
    }, {
        "date": "06-09",
        "value": 5
    }, {
        "date": "07-09",
        "value": 0
    }]
},

{
    "month": "october",
    "detail": [{
        "date": "01-10",
        "value": 10
    }, {
        "date": "02-10",
        "value": 5
    }, {
        "date": "03-10",
        "value": 5
    }, {
        "date": "04-10",
        "value": 5
    }, {
        "date": "05-10",
        "value": 5
    }, {
        "date": "07-10",
        "value": 10
    }]
}];

var combined = data.reduce(function (total, current){
  total[current.month] = current.detail.reduce(function(tot, curr) {
    return tot + curr.value;
  }, 0);
  return total;
}, {});

console.log(combined);

编辑——如果你需要保留你原来的 {"key": "..", "values", ".."} 结构

您可以像这样使用.map() 而不是.reduce()

var combined = data.map(function (elem){
  var total = elem.detail.reduce(function(total, current) {
    return total + current.value;
  }, 0);
  return {key: elem.month, values: total};
});

console.log(combined); 

// output:
// [ { key: 'september', value: 30 },
//   { key: 'october', value: 40 } ]

【讨论】:

  • 我不知道你的{"key": "september", "values": 30"}结构是否是必需的,但这肯定是最有效的方法,这样当你去查找一个月的值时,它是对单个对象的简单属性名称查找,而不必遍历对象数组并检查 "key" 属性的值
  • 谢谢你,这也很完美,我得到你的解决方案,不再对数组进行交互,而是使用 object.property。
  • @Downvoter,请评论一下为什么这个答案没有用?
猜你喜欢
  • 1970-01-01
  • 2017-06-28
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 2021-09-27
相关资源
最近更新 更多