2014-11-15 52 views
0

我是Lodash的新手,刚刚获得了使用javascript进行函数式编程的感觉。我正在使用lodash 3.0.0-pre。如何使用lodash从数组中获取前两个最接近的数字?

我有一个按顺序排列的数字和一个目标数字。

我需要一个数组,第一个和第二个最接近的数字,除非它是最后一个数字,我只需要它。我如何得到使用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]; 
} 

我可以改变它给我最近的两个而不是一个,但我相信它会遍历整个数组序列只是停止一旦它,因为它需要两个数字,而不是当数字的差异开始增加时,它可以停止。

回答

0

我建议如果你不关心性能在这里使用lodash循环功能。 只要你数组进行排序 - 这是很好用的Binary search修改后的版本,以找到最接近值的指标:

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]); 
    } 
} 

看完整的例子here

+0

你能提供一些信息,说明为什么不使用lodash进行循环? –

+0

@CalebKester,只是不要迭代整个数组,因为里面的项目已经排序了。二进制搜索适用于'O(log n)',它比'_.map' +'_.reduce'快 – Kiril

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号)

+2

_另外lodash不允许你提早取消声明 - 实际上,lodash允许中断多个循环(比如'_.forEach()')。只需从回调中返回“false”即可。请参阅[文档](https://lodash.com/docs#forEach)。 – Kiril

+0

哦,对,好点 - 可悲的是只有forIn,forEach,forOwn和变形。无论如何,使用forEach几乎只是语法糖。 – iSchluff

0

假设你的数组进行排序,并arr[0] ≤ target

var getClosests = function (arr, target) { 
    var last = _.last(arr) 
    if (target > last) { 
    return [last]; 
    } 
    var index = _.findIndex(arr, function(a) { return target - a <= 0 }); 
    neighbours = [arr[index-1], arr[index], arr[index+1]] 
    return _.chain(neighbours).sortBy(function(a) { 
    return Math.abs(a - target) }) 
    .take(2).value() 
} 

getClosests([2, 3, 5, 25, 135, 250, 300], 100); 
getClosests([2, 3, 5, 25, 135, 250, 300], 25); 
getClosests([2, 3, 5, 25, 135, 250, 300], 400); 
相关问题