Javascript 我可以在D3联接中合并新数据和现有数据吗?
我想维护一个由键索引的元素列表,它的作用类似于该键上的累加器 我有一个实时更新周期,它会重复生成在同一个键上索引的项目子集,我想在它们被吸收到现有列表中时设置累积过程的动画 在我的简单示例中,我只想计算看到每个键的次数 如果我一开始就有所有的数据,我只会使用Javascript 我可以在D3联接中合并新数据和现有数据吗?,javascript,d3.js,Javascript,D3.js,我想维护一个由键索引的元素列表,它的作用类似于该键上的累加器 我有一个实时更新周期,它会重复生成在同一个键上索引的项目子集,我想在它们被吸收到现有列表中时设置累积过程的动画 在我的简单示例中,我只想计算看到每个键的次数 如果我一开始就有所有的数据,我只会使用d3.nest(),但我不想在每次更新时重新汇总整个历史记录或重新绘制每个项目 我想使用D3将我的新数据项加入到现有选择中,并合并每个键的新旧数据,但我看不出如何避免我的新数据项仅仅覆盖任何现有数据。是否有方法将现有基准与新基准结合起来,以生
d3.nest()
,但我不想在每次更新时重新汇总整个历史记录或重新绘制每个项目
我想使用D3将我的新数据项加入到现有选择中,并合并每个键的新旧数据,但我看不出如何避免我的新数据项仅仅覆盖任何现有数据。是否有方法将现有基准与新基准结合起来,以生成合并基准
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head
<body>
<div id="stuff">
</div>
<script>
// set up a list of accumulators with count set to 0
d3.select('#stuff')
.selectAll('.grid')
.data(
d3.range(10).map(function(i) { return {key: i*2, count: 0}; }),
function(d) { return d.key; }
)
.enter().append('div')
.classed('grid', true)
.text(function(d) { return 'key: ' + d.key + ', count: ' + d.count });
// while(true) receive new items...
// now repeatedly receive a new list of items to accumulate into the existing list
var ticks = [{key: 4}, {key: 8}, {key: 14}];
// how can I combine the old and new datums during this join?
d3.selectAll('.grid')
.data(
ticks,
function(d) { return d.key; }
/* Conceptually want to provide a function to merge old and new datum */
// , function(dnew, dold) { dold.count += 1; return dold; }
)
.text(function(d) { return 'key: ' + d.key + ', count: ' + d.count });
</script>
</body>
</html>
我不确定是否有一种惯用的D3方法来处理这个问题,但实现您想要的应该很简单,即通过在绑定之前与选择数据进行比较来增加ticks数据,即:
ticks.forEach(function(t) {
var boundData = d3.selectAll('.grid').data().filter(function(d) { return d.key === t.key; });
t.count = boundData[0] ? boundData[0].count += 1 : 0;
});
注意,这也说明了潜在的新元素
请参阅:我最终使用了一个d3.map()来通过filter函数进行手动就地合并,这似乎有点像d3。这不处理新项目,但在我的例子中,我提前知道基本网格,我只是不知道每个时间步要更新哪些点
...
var tickmap = d3.map();
ticks.forEach(function(d){ tickmap.set(d.key, 1); });
d3.selectAll('.grid')
.filter(function(d) { // filter and update only matching items
if (tickmap.has(d.key)) {
d.count += tickmap.get(d.key);
return true;
} else {
return false;
}
})
.style('color', 'red') // redraw matching items in red
.text(function(d) { return 'key: ' + d.key + ', count: ' + d.count });
...
是的,这类似于我必须在您编写的同时添加的提取/过滤/更新解决方案。虽然你的forEach方法需要扫描整个网格中的每一个新元素,但是你需要阅读D3Wiki的这一部分:这不是一个很有成效的评论。我不想输入新元素,我想更新现有元素中的数据。
ticks.forEach(function(t) {
var boundData = d3.selectAll('.grid').data().filter(function(d) { return d.key === t.key; });
t.count = boundData[0] ? boundData[0].count += 1 : 0;
});
...
var tickmap = d3.map();
ticks.forEach(function(d){ tickmap.set(d.key, 1); });
d3.selectAll('.grid')
.filter(function(d) { // filter and update only matching items
if (tickmap.has(d.key)) {
d.count += tickmap.get(d.key);
return true;
} else {
return false;
}
})
.style('color', 'red') // redraw matching items in red
.text(function(d) { return 'key: ' + d.key + ', count: ' + d.count });
...