JavaScript如何在不低于给定值的情况下查找最接近的数组元素?

9
我有一个数字数组,例如[300, 500, 700, 1000, 2000, 3000],我想找到最接近的数字,但不能超过给定的数字。

例如,搜索2200将返回3000(而不是2000)。

然而,如果我搜索3200,因为数组中没有更高的数字,它应该返回3000作为唯一选择。

我可以使用以下方法获得最接近给定值的数字:

if (sizeToUse == null || Math.abs(this - monitorWidth) < Math.abs(sizeToUse - monitorWidth)) {
                sizeToUse = this;
            }

然而,我无法让整个东西正常工作。我的完整代码如下:
$(function() {

var monitorWidth = window.screen.availWidth,
    sizeToUse = null,
    upscaleImages = false;

$('.responsive-img').each(function(){

    var sizeData = $(this).attr('data-available-sizes');
    sizeData = sizeData.replace(' ', '');

    var sizesAvailable = sizeData.split(',');
    sizesAvailable.sort(function(a, b){return b-a});

    $.each(sizesAvailable, function(){
        if(upscaleImages){
            if (sizeToUse == null || Math.abs(this - monitorWidth) < Math.abs(sizeToUse - monitorWidth)) {
                sizeToUse = this;
            }
        }
        else{
            //We don't want to upscale images so we need to find the next highest image available
        }

    });

    console.log('Size to use ' + sizeToUse + ' monitor width ' + monitorWidth);

});


});

你能否删除掉与问题无关的代码的三四分之三? - James Curran
我使用以下方法对数组进行了排序:sizesAvailable.sort(function(a, b){return b-a}); - Amo
可能是从数组中获取最接近的数字的重复问题。 - Dan Mindru
4个回答

6
您可以使用以下代码:
function closest(arr, closestTo){

    var closest = Math.max.apply(null, arr); //Get the highest number in arr in case it match nothing.

    for(var i = 0; i < arr.length; i++){ //Loop the array
        if(arr[i] >= closestTo && arr[i] < closest) closest = arr[i]; //Check if it's higher than your number, but lower than your closest value
    }

    return closest; // return the value
}

var x = closest(yourArr, 2200);

Fiddle : http://jsfiddle.net/ngZ32/


这似乎是用最少的代码实现了我所需要的功能。非常棒的答案。谢谢。 - Amo

3
另一种方法是找到第一个大于或等于你想要的候选项,然后取结果,如果没有匹配项,则返回最后一个元素。
  function closestNumberOver(x, arr) {
    return arr.find(d => d >= x) || arr[arr.length - 1]
  }

1
数组必须按升序排序才能正常工作。 - enriquejr99
是的,基于样本数据,我假设(也许不正确)这是正确的。另一个在循环中使用break的答案也做出了这个假设;即找到符合条件的第一个答案是正确的。 - Tristan Reid

1
var list = [300, 500, 700, 1000, 2000, 3000];

function findBestMatch(toMatch) {
    // Assumes the array is sorted.

    var bestMatch = null;
    var max = Number.MIN_VALUE;
    var item;

    for (var i = 0; i < list.length; i++) {
        item = list[i];

        if (item > toMatch) {
            bestMatch = item;
            break;
        }

        max = Math.max(max, item);

    }

    //  Compare to null, just in case bestMatch is 0 itself.
    if (bestMatch !== null) {
        return bestMatch;
    }

    return max;

}

alert(findBestMatch(2200));
alert(findBestMatch(3200));

0
 sizesAvailable.sort(function(a, b){return a-b});  // DESCENDING sort

if(upscaleImages)   // do th eif once, not every time through the loop
{
    $.each(sizesAvailable, function()
    {  
        if (this > monitorWidth) 
            sizeToUse = this;
    }
    if (sizeToUse == null) sizeToUse = sizesAvailable[0];
}
else
{
    $.each(sizesAvailable, function()
    {  
        //We don't want to upscale images so....
    }
 }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接