首页 > 解决方案 > array.map 函数的 Javascript 问题

问题描述

这里我有一个奇怪的问题,我有一个表格的数据表:

[{grade:"a", count:1000},
{grade:"b", count:935},
.....]

但是当我使用地图功能时:

var v = data.map(function (d) { return d.count; });
console.log(v);

发现表 v 的值是{0,0,0,0,0} 如果有人知道问题可能来自哪里,我很感兴趣。

var svg = d3.select("svg"),
    margin = { top: 20, right: 20, bottom: 30, left: 40 },
    x = d3.scaleBand().padding(0.1),
    y = d3.scaleLinear();

var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

g.append("g")
    .attr("class", "axis axis--x");

g.append("g")
    .attr("class", "axis axis--y");

g.append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", "0.71em")
    .attr("text-anchor", "end")
/*.text("Count of Product")*/;

var dm = data_manager();
var data = dm.load_histo_grade_data();

console.log(data);

x.domain(data.map(function (d) { return d.grade; }));
var v = data.map(function (d) { return d.count; });
console.log(v);
y.domain([0, d3.max(data.map(function (d) { return d.count; }))]);

draw(data);

function draw(theData) {

    var margin = {top: 10, right: 30, bottom: 30, left: 40},
	width = 300 - margin.left - margin.right,
	height = 200 - margin.top - margin.bottom;

    x.rangeRound([0, width]);
    y.rangeRound([height, 0]);

    g.select(".axis--x")
	.attr("transform", "translate(0," + height + ")")
	.call(d3.axisBottom(x));

    
    g.select(".axis--y")
	.call(d3.axisLeft(y));

    // ENTER
    g.selectAll(".bar")
	.data(theData)
	.enter().append("rect")
	.attr("class", "bar")
	.attr("x", function (d) { return x(d.grade); })
	.attr("y", function (d) {
	    return y(d.count); })
	.attr("width", x.bandwidth())
	.attr("height", function (d) { return height - y(d.count); })
	.attr("fill", function(d) { return color_nutriscore_grade(d.grade); } );
}

编辑:函数 data_manager 和 load_histo_grade_data 的代码

function data_manager(){
    var dm = {};
    dm.filter = {
	WORLD:0,
	REGION:1
    };
    dm.choosen_filter = dm.filter.WORLD;
    dm.choosen_region = "Europe";
    dm.accept = function(row){
	return true;
    };
    dm.load_histo_grade_data = function(){
	data_to_update = [
	    {grade:"a", count:0.0},
	    {grade:"b", count:0.0},
	    {grade:"c", count:0.0},
	    {grade:"d", count:0.0},
	    {grade:"e", count:0.0}
	];
	d3.tsv("../tsv/hypotesis.tsv", function(error, data){
	    if(error) throw error;
	    var tmp = {
		"a":0,
		"b":1,
		"c":2,
		"d":3,
		"e":4,
	    };
	    for(var i = 1; i<data.length; i++){
		idx = tmp[data[i].grade];
		var v = data_to_update[idx].count;
		data_to_update[idx].count = (v + 1);
	    }
	});
	return data_to_update;
    };
    dm.load = function(){
	dm.load_histo_grade_data();
    }
    return dm;
}

function color_nutriscore_grade(grade){
    switch(grade) {
    case '':  return d3.rgb(191, 191, 191);
    case 'a': return d3.rgb(  0, 191,   0);
    case 'b': return d3.rgb(115, 255,   0);
    case 'c': return d3.rgb(255, 204,   0);
    case 'd': return d3.rgb(255, 102,   0);
    case 'e': return d3.rgb(255,  25,   0);
    };
}

标签: javascript

解决方案


这里的问题d3.tsv()是异步的,这意味着它将“稍后”运行您的回调。因此,您从 中返回data_to_update(所有等级均为 0)的初始值dm.load_histo_grade_data(),然后将其填充为正确的值。

您调用console.log(data)输出填充数组的原因是因为console.log具有显示活动对象的奇特功能,这意味着对象在记录后会发生变化,您在控制台中看到的内容也会发生变化。

解决方法是将回调传递给dm.load_histo_grade_data()而不是等待它返回,如下所示:

// In data_manager()
dm.load_histo_grade_data = function(callback){
    data_to_populate = [
        {grade:"a", count:0.0},
        {grade:"b", count:0.0},
        {grade:"c", count:0.0},
        {grade:"d", count:0.0},
        {grade:"e", count:0.0}
    ];
    d3.tsv("../tsv/hypotesis.tsv", function(error, data){
        if(error) throw error;
        var tmp = {
            "a":0,
            "b":1,
            "c":2,
            "d":3,
            "e":4,
        };
        for (var i = 1; i<data.length; i++){
            idx = tmp[data[i].grade];
            var v = data_to_populate[idx].count;
            data_to_populate[idx].count = (v + 1);
        }
        callback(data_to_populate)
    });
};

然后,您可以按如下方式使用它:

var dm = data_manager();
dm.load_histo_grade_data(function(data) {
    console.log(data);

    x.domain(data.map(function (d) { return d.grade; }));
    var v = data.map(function (d) { return d.count; });
    console.log(v);
    y.domain([0, d3.max(data.map(function (d) { return d.count; }))]);

    draw(data);
});

旁注:您应该在 JavaScript 中使用camelCase而不是。snake_case


推荐阅读