找到最接近给定值的索引

时间:2015-08-07 12:32:39

标签: javascript algorithm find

我有一个有序数组:

btnDrag.pos = [0, 65, 131, 196, 259, 323, 388, 453, 517];

拖动停止时触发的函数:

btnDrag.draggable({
    axis: 'x',
    containment: 'parent',
    stop: function() {
        var index = (function(){
            var new_x = btnDrag.position().left;
            // now, how to find the closest index in btnDrag.pos relative to new_x ?
            // return index;
        })();
        btnDrag.animate({
            'left': (btnDrag.pos[index] + 'px')
        });
    }
});

数组值是允许保留btnDrag的点(在轴' x')。

因此,函数必须返回最接近的索引,其值为btnDrag go。

提前致谢。

4 个答案:

答案 0 :(得分:3)

由于您的数组已排序,最快的方法是使用binary search算法的修改版本:

function closest (arr, x) {
    /* lb is the lower bound and ub the upper bound defining a subarray or arr. */
    var lb = 0, 
        ub = arr.length - 1 ;
    /* We loop as long as x is in inside our subarray and the length of our subarray is greater than 0 (lb < ub). */
    while (ub - lb > 1) {
        var m = parseInt((ub - lb + 1) / 2) ; // The middle value
        /* Depending on the middle value of our subarray, we update the bound. */
        if (arr[lb + m] > x) {
            ub = lb + m ;
        }
        else if (arr[lb + m] < x) {
            lb = lb + m ;
        }
        else {
            ub = lb + m ; lb = lb + m ;
        }
    }
    /* After the loop, we know that the closest value is either the one at the lower or upper bound (may be the same if x is in arr). */
    var clst = lb ;
    if (abs(arr[lb] - x) > abs(arr[ub] - x)) {
        clst = ub ;
    }
    return clst ; // If you want the value instead of the index, return arr[clst]
}

这是一个小提琴,你可以测试它:http://jsfiddle.net/Lpzndcbm/4/

与此处提出的所有解决方案不同,此解决方案在O(log(n))中运行,而不在O(n)中运行。如果您不熟悉complexity,则表示此算法会在最多 N循环中找到大小为O(log(N))的数组中的最接近值其他人会在最多N循环中找到它(使用N = 10000,它会因log(10000) ~ 14(二进制日志)而产生很大的不同。)

请注意,如果您的数组非常小,这可能比天真算法慢。

答案 1 :(得分:1)

这样的东西?

var closest = btnDrag.pos.reduce(function (prev, curr) {
 return (Math.abs(curr - new_x) < Math.abs(prev - new_x) ? curr : prev);
});

答案 2 :(得分:1)

你去了:

function closest(list, x) {
    var min,
        chosen = 0;
    for (var i in list) {
        min = Math.abs(list[chosen] - x);
        if (Math.abs(list[i] - x) < min) {
            chosen = i;
        }
    }
    return chosen;
}

每次计算最小距离,并根据最小值更新所选值。 (http://jsbin.com/dehifefuca/edit?js,console

答案 3 :(得分:0)

简单的for循环可以做到:

var btnDrag = {};
btnDrag['pos'] = [0, 65, 131, 196, 259, 323, 388, 453, 517]; 
new_x = 425;


    var index = -1;

    for (var i = 0; i < btnDrag.pos.length; i++)
    {
        if (i < btnDrag.pos.length-1) //loop till i is at 2 positions from the end.
        {
           //value has to be less then the selected value + 1
           if (new_x < btnDrag.pos[i+1])
           {

               //calculate the half between the values and add it with the first value
               // test if new_x is larger then that value.
               if ((btnDrag.pos[i+1] - btnDrag.pos[i])/2 + btnDrag.pos[i] > new_x) 
               {
                   index = i;
                   break;
               }
               else
               {
                   index = i+1;
                   break;
               }
           }
        }
        else
        {
           //edge cases.
           if (new_x < 0)
           {
                index = 0;
           }
           else
           {
              index = btnDrag.pos.length-1;
           }      
       
        }
    }

document.body.innerHTML = btnDrag['pos'][index] + " (" + index + ")";