bisect 背后的基本思想是这样的:
考虑您提到的数组 - var data = [3, 6, 2, 7, 5, 4, 8]
您想在data 数组中插入一个新值,比如说3.5,并想知道如何“分区”它。换句话说,您想知道3.5 的索引是什么,如果它是在对data 数组进行排序时插入的。
var data = [3, 6, 2, 7, 5, 4, 8]
//Sorted data
[2, 3, 4, 5, 6, 7, 8]
//You want to insert 3.5
The sorted array after insertion of 3.5 should look something like:
[2, 3, 3.5, 4, 5, 6, 7, 8]
So the index of 3.5 in sorted data array is "2".
在某些情况下,您想知道该元素的插入如何“平分”或“分割”一个数组。在这种情况下,您需要先对该数组进行排序,然后执行我们所说的 Binary Search 来找出插入该元素的正确位置。
bisectLeft 和bisectRight 在您想要输入数组中已存在的元素的情况下注意澄清异常情况。假设您想在数组中输入另一个3。有两种情况:
3* -> The new element to be entered
[2, 3*, 3, 4, 5, 6, 7, 8] -> entered at "1" (array is still sorted)
[2, 3, 3*, 4, 5, 6, 7, 8] -> entered at "2" (array is still sorted)
因此,根据我们如何处理这种歧义,我们可以将该元素输入到现有元素的“左”或“右”。来自docs(标记重点):
返回的插入点 i 将数组分成两半,以便所有 v x for v in array.slice(lo, i) 用于左侧,所有 v >= x for v in array.slice(i, hi) for the right side.
在bisectLeft 中,我们得到1 作为合适的索引,所有重复的条目将在该索引的右侧,而bisecRight 中的情况正好相反。
既然您知道bisectLeft 和bisectRight 是如何工作的,那么bisector 只允许我们定义一个自定义comparator 或accessor 函数来对值进行分区或理解 和 > 也适用于对象。
所以这段代码:
var bisect = d3.bisector(function(d) { return d.date; }).right;
var bisect = d3.bisector(function(a, b) { return a.date - b.date; }).right;
只需指定使用bisectRight 选项并返回一个合适的索引以插入一个元素,假设数组已排序(按升序排列)。
因此,如果我要以您的示例为基础,并假设一个名为 bisect 的 bisector。你做到了:
bisect(data, 3); //it would return 2.
我希望它可以澄清事情并让您朝着正确的方向开始。