我无法找到如何根据JavaScript数组确定元素属于哪个区间。我想要来自Python的bisect.bisect_left
行为。以下是一些示例代码:
import bisect
a = [10,20,30,40]
print(bisect.bisect_left(a,0)) #0 because 0 <= 10
print(bisect.bisect_left(a,10)) #0 because 10 <= 10
print(bisect.bisect_left(a,15)) #1 because 10 < 15 < 20
print(bisect.bisect_left(a,25)) #2 ...
print(bisect.bisect_left(a,35)) #3 ...
print(bisect.bisect_left(a,45)) #4
我知道这很容易实现,但为什么重新发明轮子?
答案 0 :(得分:1)
JavaScript中没有内置的二分函数,所以你必须自己动手。这是我对车轮的个人改造:
var array = [10, 20, 30, 40]
function bisectLeft (array, x) {
for (var i = 0; i < array.length; i++) {
if (array[i] >= x) return i
}
return array.length
}
console.log(bisectLeft(array, 5))
console.log(bisectLeft(array, 15))
console.log(bisectLeft(array, 25))
console.log(bisectLeft(array, 35))
console.log(bisectLeft(array, 45))
function bisectRight (array, x) {
for (var i = 0; i < array.length; i++) {
if (array[i] > x) return i
}
return array.length
}
答案 1 :(得分:1)
万一其他人落在这里,这是bisect_left的实现,该实现实际上在O(log N)中运行,并且无论列表元素之间的间隔如何都应工作。注意,不是对输入列表进行 排序的,按原样,如果将未排序的列表传递给它,很可能会破坏堆栈。它也只设置为可以与数字一起使用,但是它应该很容易适应它以接受比较功能。以此为起点,不一定是您的目的地。改进当然值得欢迎!
function bisect(sortedList, el){
if(!sortedList.length) return 0;
if(sortedList.length == 1) {
return el > sortedList[0] ? 1 : 0;
}
let lbound = 0;
let rbound = sortedList.length - 1;
return bisect(lbound, rbound);
// note that this function depends on closure over lbound and rbound
// to work correctly
function bisect(lb, rb){
if(rb - lb == 1){
if(sortedList[lb] < el && sortedList[rb] >= el){
return lb + 1;
}
if(sortedList[lb] == el){
return lb;
}
}
if(sortedList[lb] > el){
return 0;
}
if(sortedList[rb] < el){
return sortedList.length
}
let midPoint = lb + (Math.floor((rb - lb) / 2));
let midValue = sortedList[midPoint];
if(el <= midValue){
rbound = midPoint
}
else if(el > midValue){
lbound = midPoint
}
return bisect(lbound, rbound);
}
}
console.log(bisect([1,2,4,5,6], 3)) // => 2
console.log(bisect([1,2,4,5,6], 7)) // => 5
console.log(bisect([0,1,1,1,1,2], 1)) // => 1
console.log(bisect([0,1], 0)) // => 0
console.log(bisect([1,1,1,1,1], 1)) // => 0
console.log(bisect([1], 2)); // => 1
console.log(bisect([1], 1)); // => 0
答案 2 :(得分:0)
使用D3数组npm。
const d3 = require('d3-array');
var a = [10,20,30,40];
console.log(d3.bisectLeft(a,0));
console.log(d3.bisectLeft(a,10));
console.log(d3.bisectLeft(a,15));
console.log(d3.bisectLeft(a,25));
console.log(d3.bisectLeft(a,35));
console.log(d3.bisectLeft(a,45));
输出:
0
0
1
2
3
4
答案 3 :(得分:-1)
比之前接受的适用于相同大小间隔的答案更快的方法是:
var array = [5, 20, 35, 50]
//Intervals:
// <5: 0
// [5-20): 1
// [20-35): 2
// [35-50): 3
// >=50: 4
var getPosition = function(array, x) {
if (array.length == 0) return;
if (array.length == 1) return (x < array[0]) ? 0 : 1;
return Math.floor((x - array[0]) / (array[1] - array[0])) + 1
}
console.log(getPosition(array, 2)); //0
console.log(getPosition(array, 5)); //1
console.log(getPosition(array, 15));//1
console.log(getPosition(array, 20));//2
console.log(getPosition(array, 48));//3
console.log(getPosition(array, 50));//4
console.log(getPosition(array, 53));//4
console.log("WHEN SIZE: 1")
array = [5];
//Intervals:
// <5: 0
// >=5: 1
console.log(getPosition(array, 3));
console.log(getPosition(array, 5));
console.log(getPosition(array, 6));