Javascript 获取与数组中的值最接近的两个数字

Javascript 获取与数组中的值最接近的两个数字,javascript,numbers,Javascript,Numbers,假设我有一个数字数组,如下所示: var a = [4, 5, 7, 9, 12, 15, 18, 19, 20, 23, 27, 31]; 它是按升序排序的,现在,假设我选择一个值x: var x = 13; 如何找到最接近x的两个值 在这种情况下,它是12和15,但是对于任何给定的x,我如何得到这两个值,如果x小于最小值,那么只返回最小值,如果它大于最大值,那么只返回最大值,就像如果x=3,那么只返回一个值,4 我试过这个: function getClosest(a, x) {

假设我有一个数字数组,如下所示:

var a = [4, 5, 7, 9, 12, 15, 18, 19, 20, 23, 27, 31];
它是按升序排序的,现在,假设我选择一个值x:

var x = 13;
如何找到最接近x的两个值

在这种情况下,它是12和15,但是对于任何给定的x,我如何得到这两个值,如果x小于最小值,那么只返回最小值,如果它大于最大值,那么只返回最大值,就像如果x=3,那么只返回一个值,4

我试过这个:

function getClosest(a, x) {
    for (var i = 0; i < a.length - 1; i++) {
        var c1 = a[i],
            c2 = a[i + 1];

        if (x > c1 && x < c2) return [c1, c2];
        else if (i == 0) return [c1];
        else if (i == a.length - 2) return [c2];
    }
}
函数getClosest(a,x){ 对于(变量i=0;ic1&&x
现在,这是我的方法,您将如何解决这个问题/最有效的解决方案是什么?

我相信您的代码没有按预期工作,因为如果前两个元素小于x,它将返回第一个元素。同样,你也忽略了x在a中的情况

如果找到正确答案,则代码将直接返回,同时具有线性运行时

因为a是排序的,所以可以使用二进制搜索方法将代码优化为O(logn)

将[0]和[n]设为上限和下限。将x与a进行比较[n/2]。如果x 事先注意xmax(a)的情况。 单独处理a中的案例x。

您可以使用和短路

函数最近(值,数组){
var结果=[];
array.some(函数(a){
如果(a>值){
返回结果。推送(a);
}
结果=[a];
返回一个===值;
});
返回结果;
}
log(最近的(13、[4、5、7、9、12、15、18、19、20、23、27、31]);
log(最近的(3、[4、5、7、9、12、15、18、19、20、23、27、31]);
log(最接近的(50、[4,5,7,9,12,15,18,19,20,23,27,31]);

log(最近的(19、[4、5、7、9、12、15、18、19、20、23、27、31])这与
sort()
slice()

var a=[4,5,7,9,12,15,18,19,20,23,27,31];
函数getClosest(num,ar){
if(numar[ar.length-1]){
返回应收账款[应收账款长度-1];
}否则{
返回ar.sort((a,b)=>Math.abs(a-num)-Math.abs(b-num)).slice(0,2);
}
}

console.log(getClosest(11,a))
这是一个快速解决方案,它还涵盖了最低和最高边界:

var a = [4, 5, 7, 9, 12, 15, 18, 19, 20, 23, 27, 31];

function getClosest(a, x) {
    var min = Math.min.apply(null, a), max = Math.max.apply(null, a), i, len;

    if (x < min) {   // if x is lower than the lowest value
        return min; 
    } else if (x > max) {  // if x is greater than the 'greatest' value
        return max;
    }
    a.sort();
    for (i = 0, len = a.length; i < len; i++) {
        if (x > a[i] && x < a[i + 1]) {
            return [a[i], a[i + 1]];
        }
    }
}

console.log(getClosest(a, 13));   // [12, 15]
console.log(getClosest(a, 3));    // 4
console.log(getClosest(a, 33));   // 31
console.log(getClosest(a, 25));   // [23, 27]
var a=[4,5,7,9,12,15,18,19,20,23,27,31];
函数getClosest(a,x){
var min=Math.min.apply(null,a),max=Math.max.apply(null,a),i,len;
如果(xmax){//如果x大于“最大”值
返回最大值;
}
a、 排序();
对于(i=0,len=a.length;ia[i]&&x
如果数字存在,则查找数组。如果没有,则将其推送到阵列。对数组进行排序,并获取该数字的索引。如果该数字是第一个(第零个)条目,则返回数组的第二个元素(arr[1])。如果是最后一个,则返回前面的元素。 否则,返回左右邻居

function closest_two(n, arr) {
    if (arr.indexOf(n) == -1) {
        arr.push(n);
    }
    arr.sort(function(a,b) { return a-b; })
    p = arr.indexOf(n);
    if (p==0) { return arr[1]; }
    if (p == (arr.length - 1)) { return arr[p-1]; }

  return[arr[p-1], arr[p+1]]
}

我的方法是:如果x不在a中,将x推到a上,然后移动。然后,设i=indexOf(x),如果存在,则返回[i-1],如果存在,则返回[i+1]。a被克隆,因为push会修改它

var a = [4, 5, 7, 9, 12, 15, 18, 19, 20, 23, 27, 31];
function neighbors(a,x){
b=a.slice(0);//clone a
if (a.indexOf(x) < 0) {//push x onto a if x not in a
    b.push(x);
    b.sort((a,b)=>a-b); //resort
    }
var i=b.indexOf(x);
return [i-1 in b ? b[i-1] : null, i+1 in b ? b[i+1] : null].filter(Number);
}

neighbors(a,13);//[12,15]
neighbors(a,12);//[9,15]
neighbors(a,5);//[4,7]
neighbors(a,4);//[5]
neighbors(a,3);//[4]
neighbors(a,27);//[23,31]
neighbors(a,28);//[27,31]
neighbors(a,31);//[27]
neighbors(a,32);//[31]
var a=[4,5,7,9,12,15,18,19,20,23,27,31];
函数邻域(a,x){
b=a.slice(0);//克隆a
如果(a.indexOf(x)<0){//如果x不在a中,则将x推到a上
b、 推(x);
b、 排序((a,b)=>a-b);//
}
var i=b.indexOf(x);
返回b?b[i-1]中的[i-1]:null,b?b中的i+1[i+1]:null]。过滤器(编号);
}
邻居(a,13)//[12,15]
邻居(a,12)//[9,15]
邻居(a,5)//[4,7]
邻居(a,4)//[5]
邻居(a,3)//[4]
邻居(a,27)//[23,31]
邻居(a,28)//[27,31]
邻居(a,31)//[27]
邻居(a,32)//[31]

假设数组已排序,则可以使用二进制搜索。它只会是
O(lgn)
,比你的
O(n)
方法要小

function lowerBound(arr, x, from=0, to=arr.length) {
  if(from >= to) return to-1;
  var m = Math.floor( (from+to)/2 );
  if(a[m] < x) return lowerBound(arr, x, m+1, to);
  return lowerBound(arr, x, from, m);
}
function upperBound(arr, x, from=0, to=arr.length) {
  if(from >= to) return to;
  var m = Math.floor( (from+to)/2 );
  if(a[m] > x) return upperBound(arr, x, from, m);
  return upperBound(arr, x, m+1, to);
}
function getClosest(a, x) {
  var lb = lowerBound(a, x),
      ub = upperBound(a, x, lb+1),
      res = [];
  if(lb >= 0) res.push(a[lb]);
  if(ub < a.length) res.push(a[ub]);
  return res;
}
函数下限(arr,x,from=0,to=arr.length){
如果(从>=到)返回到-1;
var m=数学楼层((从+到)/2);
如果(a[m]=到)返回到;
var m=数学楼层((从+到)/2);
如果(a[m]>x)返回上限(arr,x,from,m);
返回上限(arr,x,m+1,to);
}
函数getClosest(a,x){
var lb=下限(a,x),
ub=上限(a,x,lb+1),
res=[];
如果(lb>=0)res.push(a[lb]);
if(ub
为什么你认为你的代码很草率?究竟哪种方法会更好?代码审查可能会更好question@NinaScholz只有[19],距离与任何事情都没有关系我投票结束这个问题,因为这个问题属于代码Review@AndersTornblad您给出的原因实际上并没有解释为什么堆栈溢出的问题是离题的<代码>数组。reduce
迭代数组中的所有值,但如果匹配项,则可以提前停止循环found@RomanPerekhrest,请参阅编辑。