平分对象数组:不是所有对象都被枚举了吗?

Bisecting an array of objects: are not all of them enumerated?

这是我的平分线:

var bisectDate = d3.bisector(function(d: any) {
  console.log('d date ', d.date);
  return d.date;
}).left;

我有一组日期(总共 78 个),但在我的平分线上它只重复记录 5 个,如下所示?

timesDataPath  (78) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, ...]
App.tsx:122 d date  Mon Aug 12 2019 12:45:00 GMT+0800 (Singapore Standard Time)
App.tsx:122 d date  Mon Aug 12 2019 11:05:00 GMT+0800 (Singapore Standard Time)
App.tsx:122 d date  Mon Aug 12 2019 10:15:00 GMT+0800 (Singapore Standard Time)
App.tsx:122 d date  Mon Aug 12 2019 09:50:00 GMT+0800 (Singapore Standard Time)
App.tsx:122 d date  Mon Aug 12 2019 09:40:00 GMT+0800 (Singapore Standard Time)
App.tsx:122 d date  Mon Aug 12 2019 09:35:00 GMT+0800 (Singapore Standard Time)

怎么会这样?我在数组中的对象是这样的:

{
  1. open: "25891.8496"
  2. high: "25896.8809"
  3. low: "25890.6797"
  4. close: "25893.1504"
  5. volume: "3205446"
  date: Mon Aug 12 2019 16:00:00 GMT+0800 (Singapore Standard Time) {}
}

我是这样使用它的:

.on('mousemove', function() {
    var mouse = d3.mouse(this);
    var mouseDate = xScale.invert(mouse[0]);
    var i = bisectDate(timesDataPath, mouseDate); 

timesDataPath 是我用于 x 轴和 y 轴的,我对图表没有任何问题,只是将这部分作为指针不起作用。

这是预期的行为

如果您查看 d3.bisectorsource code,您会发现它并没有按照您的想法迭代整个数组。看看这里:

while (lo < hi) {
    var mid = lo + hi >>> 1;
    if (compare(a[mid], x) > 0) hi = mid;
    else lo = mid + 1;
}

有趣的部分在于:var mid = lo + hi >>> 1;。这个按位(名为 zero-fill right shift)所做的是计算数组的 中点

在你的例子中,数组有 78 个元素。因此:

console.log(0 + 78 >>> 1)

并且它不断获取剩余部分的中点,一次又一次,直到找到元素。看看这里:

let lo = 0,
  hi = 78;
while (lo < hi) {
  let mid = lo + hi >>> 1;
  console.log(mid)
 lo = mid + 1;
}

对于 78 个元素的数组,它执行了 6 次(不是你提到的 5 次),这就是为什么你看到 console.log 只工作了 6 次。

看看这个演示,一个包含 78 个元素的数组,console.log 工作了 7 次:

const data = d3.range(78);

const bisect = d3.bisector(function(d) {
  console.log(d);
  return d;
}).left;

bisect(data, 5);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

现在让我们将数组增加到 1000 个元素。 console.log 工作 10 次:

const data = d3.range(1000);

const bisect = d3.bisector(function(d) {
  console.log(d);
  return d;
}).left;

bisect(data, 5);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>