Javascript 如何使用lodash从数组中获取与目标最近的前两个数字?
我是lodash的新手,刚刚开始使用javascript进行函数式编程。我正在使用lodash 3.0.0-pre 我有一个有序的数字数组和一个目标数字 我需要一个包含第一个和第二个最近数字的数组,除非它是最后一个数字,否则我只需要它。我如何使用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
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;iconsole.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]);
}
}