d3.map()函数未返回预期结果,set方法自定义赋值疑问
解决D3.js中d3.map构建键值对的问题
我明白你遇到的问题了——你想把CSV数据转换成以county为键、rate为值的d3.map,但当前的写法并没有正确批量处理数组元素,反而把索引当成了键,还错误地传入了函数作为set的参数。
为什么你的写法不生效?
首先,d3.map(data)本身会把传入的数组转换成一个以数组索引为键、数组元素为值的map。之后调用.set(function(d) {d.county}, function(d) {d.rate})时,set方法会把你传入的函数直接转换成字符串作为键,另一个函数作为值,这显然不是你想要的批量映射逻辑。
另外,你原来在d3.queue里的代码其实也有问题:每次处理一行CSV数据时,你都新建了一个d3.map()并调用set,但这个map并没有被保存下来,相当于做了无用功。正确的原写法应该是先初始化一个全局的map,再在回调里往里面添加键值对。
正确的实现方式
要从已加载的CSV数据data构建目标map,你需要手动遍历数据并逐个添加键值对,或者用数组方法先转换为普通对象再传入d3.map。这里提供两种常用方法:
方法1:forEach遍历初始化
这是最直观的方式,先创建空map,再遍历数据填充:
// 初始化空的d3.map var mapdata = d3.map(); // 遍历CSV数据数组,逐个添加键值对 data.forEach(function(d) { // d.county作为键,+d.rate把字符串转为数字作为值 mapdata.set(d.county, +d.rate); });
方法2:用reduce先转普通对象再转d3.map
如果你喜欢更简洁的写法,可以先用Array.reduce把数组转换成普通键值对对象,再传给d3.map:
var mapdata = d3.map( data.reduce(function(acc, d) { acc[d.county] = +d.rate; return acc; }, {}) // 初始值为空对象 );
对应原队列代码的修正
如果你还是想保留d3.queue的写法,正确的版本应该是先初始化map,再在CSV处理回调中填充它:
var mapdata = d3.map(); d3.queue() .defer(d3.json, 'counties.json') .defer(d3.csv, 'employmentdata.csv', function(d) { // 往已有的map里添加键值对,而不是每次新建map mapdata.set(d.county, +d.rate); }) .await(function(error, counties, employment) { if (error) throw error; // 在这里使用counties和mapdata });
这样就能得到你想要的、以county为键的d3.map了。
内容的提问来源于stack exchange,提问作者user3611
相关产品推荐
相关产品推荐

