javascript - 在转换 D3.js 数据时使用 forEach() 循环的替代方案

标签 javascript jquery d3.js time-series timeserieschart

我仍在努力解决此错误,如 earlier post on StackOverflow.com 中所示。 。我已经隔离了问题的原因,即在我的 D3.js 代码中它无法迭代“对象”。我的原始数据源是 RESTful Web API。使用 jQuery 和 JavaScript 函数,我可以将值加载到名为“数据集”的变量中。当我将“数据集”的内容输出为警报,或使用 jQuery 将其写入 html 元素时,所有数据都在那里。太多的 D3.js 示例使用硬编码的数据文件。因此,重要的是要注意,当我使用相同数据的硬编码版本时,一切正常,但我仅限于使用这个动态虚拟数据变量。

当我运行代码时,它在此函数处崩溃:

    dataset.forEach(function(d) {
        d.theTime = parseDate(d.theTime);
        d.theValue = +d.theValue;
    });

错误消息为Uncaught TypeError:无法读取未定义的属性“length”

当我在此函数之前使用 console.log(typeof(dataset)) 时,我得到“object”。如果有任何 D3.js 导师正在阅读本文,我可以选择哪些方式来转换这些数据?我已经探索了几个但没有成功。

//============= 附加 01 ==========================

因为这里请求的是“数据集”,可以在上面的早期帖子链接( Parsing Time Series Data using D3.js )中查看:

    var dataset = [
    {'theTime': '2016/07/12 15:58:40', 'theValue': 1123.07275390625},
    {'theTime': '2016/07/12 16:21:10', 'theValue': 1055.6793212890625},
    {'theTime': '2016/07/12 16:45:40', 'theValue': 962.4850463867188},
    {'theTime': '2016/07/12 17:14:40', 'theValue': 831.2259521484375},
    {'theTime': '2016/07/12 17:55:10', 'theValue': 625.3046875}
    ];

//============= 附加 02 ==========================

引用 Gerardo 的问题,“数据集”变量被“加载”(我认为),因为代码位于“$.get”函数内,该函数组装“数据集”变量,如下所示:

    //~ Populate the 'dataset':
    var dataset = [];
    $.get(url, function(data){
        var itemCount = data.Items.length;
        var commaCount = itemCount - 1;
        for(i=0; i<itemCount; i++){
            if(i == commaCount){
                dataset.push("{'theTime': '" + formattedDateTime(data.Items[i].Timestamp) + "', 'theValue': " + data.Items[i].Value + "}");
            }
            else {
                dataset.push("{'theTime': '" + formattedDateTime(data.Items[i].Timestamp) + "', 'theValue': " + data.Items[i].Value + "},");
            }
        }
    //~ ALL THE D3 CODE IS INSIDE THIS '$.get' FUNCTION
    });

//============= 附加 03 ==========================

我成功了!

我将在下面发布修改后的工作代码。但对于关注这篇文章的人,我想解释一下我的发现。

Mark 建议更改 dataset.push() 以删除所有引号。这给了我对象而不是字符串。经过一番故障排除后,它终于按预期显示了(太兴奋了!),谢谢马克,你的建议成功了。

这是修改后的代码:

    //~ Populate the 'dataset':
    var dataset = [];
    $.get(url, function(data){
        var itemCount = data.Items.length;
        var commaCount = itemCount - 1;
        for(i=0; i<itemCount; i++){
            dataset.push({theTime: formattedDateTime(data.Items[i].Timestamp), theValue: data.Items[i].Value});
        }

        var margin = {top: 20, right: 20, bottom: 30, left: 50};
        var width = 960 - margin.left - margin.right;
        var height = 500 - margin.top - margin.bottom;
        var parseDate = d3.time.format("%Y/%m/%d %H:%M:%S").parse;

        var x = d3.time.scale()
          .range([0, width]);

        var y = d3.scale.linear()
          .range([height, 0]);

        var xAxis = d3.svg.axis()
          .scale(x)
          .orient("bottom");

        var yAxis = d3.svg.axis()
          .scale(y)
          .orient("left");

        var line = d3.svg.line()
          .x(function(d) { return x(d.theTime); })
          .y(function(d) { return y(d.theValue); });


        var svg = d3.select("#myChart").append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
        .append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        dataset.forEach(function(d) {
            d.theTime = parseDate(d.theTime);
            d.theValue = parseFloat(d.theValue);
        });

         x.domain(d3.extent(dataset, function(d) { return d.theTime; }));
         y.domain(d3.extent(dataset, function(d) { return d.theValue;}));

         svg.append("g")
                 .attr("class", "x axis")
                 .attr("transform", "translate(0," + height + ")")
                 .call(xAxis);

         svg.append("g")
                 .attr("class", "y axis")
                 .call(yAxis)
                 .append("text")
                 .attr("transform", "rotate(-90)")
                 .attr("y", 6)
                 .attr("dy", ".71em")
                 .style("text-anchor", "end")
                 .text("M³/hr");

         svg.append("path")
                 .datum(dataset)
                 .attr("class", "line")
                 .attr("d", line);
    });

      //~~~ Format The Date:
      function formattedDateTime(dateAndTime) {
            var d = new Date(dateAndTime);
            var numDate = d.getDate();
            var numMonth = d.getMonth() + 1;
            var numYear = d.getFullYear();
            var numHours = d.getHours();
            var numMinutes = d.getMinutes();
            var numSeconds = d.getSeconds();
            numDate = (numDate < 10) ? "0" + numDate : numDate;
            numMonth = (numMonth < 10) ? "0" + numMonth : numMonth;
            numHours = (numHours < 10) ? "0" + numHours : numHours;
            numMinutes = (numMinutes < 10) ? "0" + numMinutes : numMinutes;
            numSeconds = (numSeconds < 10) ? "0" + numSeconds : numSeconds;

            return numYear + "/" + numMonth + "/" + numDate + " " + numHours + ":" + numMinutes + ":" + numSeconds;
      };

最佳答案

如果您不确定是否会获得“对象数组”或“具有键/值的对象”,那么我会在库 'lodash' 中使用 _.forEach将迭代对象数组或对象的键/值。

关于javascript - 在转换 D3.js 数据时使用 forEach() 循环的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38362695/

相关文章:

javascript - 所有圆形元素都相互卡住

d3.js - D3 : Can't select a subset of my dataset

javascript - 创建了条形图,但高度没有往复变化

javascript - 将数据发送到JS

javascript - 如何在 ui-grid 中获取过滤后的行?

javascript - 如何扩展文本区域以垂直和水平适应文本?

jquery - 逐个淡出多个元素

javascript - 我应该如何打包插件函数以在验证指令中使用?

javascript - AngularJS 保存后数据不一致

javascript - 规范化 Javascript 对象属性的 Clean 方法