Javascript 如何使用lodash从数组中获取与目标最近的前两个数字?

Javascript 如何使用lodash从数组中获取与目标最近的前两个数字?,javascript,lodash,Javascript,Lodash,我是lodash的新手,刚刚开始使用javascript进行函数式编程。我正在使用lodash 3.0.0-pre 我有一个有序的数字数组和一个目标数字 我需要一个包含第一个和第二个最近数字的数组,除非它是最后一个数字,否则我只需要它。我如何使用lodash获得它 我发现: function getClosest(array, target) { var tuples = _.map(array, function(val) { return [val, Math.abs

我是lodash的新手,刚刚开始使用javascript进行函数式编程。我正在使用lodash 3.0.0-pre

我有一个有序的数字数组和一个目标数字

我需要一个包含第一个和第二个最近数字的数组,除非它是最后一个数字,否则我只需要它。我如何使用lodash获得它

我发现:

function getClosest(array, target) {
    var tuples = _.map(array, function(val) {
        return [val, Math.abs(val - target)];
    });
    return _.reduce(tuples, function(memo, val) {
        return (memo[1] < val[1]) ? memo : val;
    }, [-1, 999])[0];
}

我可以将其更改为最接近的两个而不是一个,但我相信它将在整个数组中排序,而不是在它拥有所需的两个数字时停止,因为当数字差异开始增大时,它可以停止。

这不是一个真正的lodash任务,因为它不是一个简单的n->n或n->1转换。此外,lodash不允许您提前取消声明

无论如何,这里有一个解决方案:

var array= [2, 3, 5, 25, 135, 250, 300];

function getClosest(array, target) {
    var tuples = _.map(array, function(val) {
        return [val, Math.abs(val - target)];
    });

    var prev= [0, Number.MAX_VALUE];
    for(var i=0; i<tuples.length; i++){
        if(tuples[i][1] < prev[1]){
            prev= tuples[i];
        }else{
            if(i<2 || tuples[i][1] < tuples[i-2][1]){
                return [prev[0], tuples[i][0]];
            }else{
                return [prev[0], tuples[i-2][0]];
            }
        }
    }
    return [prev[0]];
}

console.log(getClosest(array, 3));

可以通过使用牛顿法找到最近的元素,然后查看之前和之后的元素来进行优化。如果数组中有50000个数字^ ^

假设数组已排序且arr[0]≤ 目标:


如果您关心性能,我建议不要在这里使用lodash循环函数。 数组一经排序,最好使用的修改版本查找最接近值的索引:

function closestIndex(arr, target) {
    var i = 0, j = arr.length - 1, k;   

    while (i <= j) {
       k = Math.floor((i+j) / 2);
       if (target === arr[k] || Math.abs(i - j) <= 1 ) {
           return k;
       } else if (target < arr[k]) {
           j = k-1;
       } else {
           i = k+1;
       }
    }
    return -1;
}
然后简单地比较阵列中的相邻元素:

if (_.isNumber(arr[closestIndex - 1]) && _.isNumber(arr[closestIndex + 1])) {
    if (Math.abs(target - arr[closestIndex - 1]) < Math.abs(target - arr[closestIndex + 1])) {
        result.push(arr[closestIndex - 1]);
    } else {
        result.push(arr[closestIndex + 1]);
    }
}
请参阅完整示例。

在数组中找到两个达到给定目标的壁橱:没有Lodash

函数findClosetgivenList,目标{ var优先; var第二; var finalCollection=[givenList[0],givenList[1]; givenList.forEachitem,firtIndex=>{ 第一个=项目; 对于let i=firtIndex+1;i最终收集[0]+最终收集[1]{ finalCollection=[第一,第二]; } } } }; 返还最终收款; } 风险值计数=[2,42,82,329,122,40,162,202,3,5,242,282,322,35,362]; var目标=80;
console.logfindClosetcounts,目标;此外,lodash不允许您提前取消语句-实际上,lodash允许中断几个循环,如u.forEach。只需从回调返回false。看。哦,对了,很好的观点——遗憾的是,只有福林、福雷奇、福隆和变换。无论如何,使用forEach几乎只是语法上的甜点。你能提供一些为什么不使用lodash进行循环的信息吗?@CalebKester,只是不要迭代整个数组,因为里面的项已经排序好了。二进制搜索适用于比u.map+uu.reduce更快的Olog n
if (_.isNumber(arr[closestIndex - 1]) && _.isNumber(arr[closestIndex + 1])) {
    if (Math.abs(target - arr[closestIndex - 1]) < Math.abs(target - arr[closestIndex + 1])) {
        result.push(arr[closestIndex - 1]);
    } else {
        result.push(arr[closestIndex + 1]);
    }
}