我在javascript中有一个整数数组,[5,10,15,20,25,30,35]
给定数字x时,如何在数组中找到最接近该数字的元素?
如果数字超过一个值,但不到下一个数字的一半,我会选择较小的值,如果它超过下一个数字的一半,我会选择更高的数字。
例如7会返回5,但8会返回10.我怎样才能完成此操作?任何帮助或提示将不胜感激。我搜索过,找不到解决方案。我确信这很常见。
答案 0 :(得分:25)
最简单的做法可能是根据距参考值x的距离进行排序,然后选择第一项。
内置Array.prototype.sort()
可以使用比较函数,该函数将从数组中调用值对。然后关键是传递一个比较函数,该函数根据它们与参考值x的距离来比较这两个值。
let x = 8;
let array = [5, 10, 15, 20, 25, 30, 35];
let closest = array.sort( (a, b) => Math.abs(x - a) - Math.abs(x - b) )[0];
请参阅此简单demo。
答案 1 :(得分:16)
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];
}
如果使用函数方法适用,那么您可以将集合映射到(值,距离)的元组,然后将该组元组减少到具有最小距离的元组。我们返回该元组中的值。
解释_.map
的用法。您将数组中的所有值映射到新值,该函数将返回新值的数组。在这种情况下是一个元组数组。
解释_.reduce
的用法。您将数组减少为单个值。你传入一个数组和一个备忘录。当您在阵列中移动时,备忘录是您的“运行计数器”。在这种情况下,我们检查当前元组是否比备忘录更接近,如果是,则将其作为备忘录。然后我们在最后返回备忘录。
上面的代码片段依赖于underscore.js来删除功能样式javascript的细节
答案 2 :(得分:11)
您的示例列表已排序。如果总是如此,则二进制搜索您的号码。如果找不到确切的数字,请通过检查数字 所在的两个数字来结束二进制搜索,并返回最接近的数字。小心所有数字都大于或者都小于目标数
的边缘情况如果列表并不总是排序,则通过列表跟踪最大数字&lt; =目标数量和最小数量&gt; =目标数量。返回最接近目标的那个。
在任何一个解决方案中,如果你在[1,3]中搜索2,你需要决定支持哪一方。
答案 3 :(得分:5)
创建一个与原始数组大小相同的临时数组,并用x和数组元素之间的差异填充它。
例如,让临时数组为temp [],原始数组为[]:
temp[i]=Math.abs(x-a[i]);
然后,将temp []中最小值的索引返回给用户。
答案 4 :(得分:0)
假设数组已排序,请逐步遍历数组中的每个相邻整数对。对于每对(例如“5和10”或“20和25”),测试 x 是否位于它们之间,如果是,则返回更接近 x (偏向较低者)。
当 x 小于第一个数字(返回第一个数字)或大于最后一个数字(返回最后一个数字)时,您还需要一个特殊情况。
如果数组未排序,请先排序。
答案 5 :(得分:0)
我创建了自己的功能,因为我找不到符合我要求的任何功能。
function closest_number(quantities, number, closest_factor)
{
if (closest_factor == 'ceil')
{
quantities.sort(function(a, b)
{
return a - b
}
);
for (var i = 0; i < quantities.length; i++)
{
if (quantities[i] >= number)
{
return quantities[i];
}
last_value = quantities[i];
}
return last_value;
}
else if (closest_factor == 'floor')
{
quantities.sort(function(a, b)
{
return a - b
}
);
min_value = quantities[0];
for (var i = 0; i < quantities.length; i++)
{
if (number == quantities[i])
{
return number;
}
else if (quantities[i] < number)
{
min_value = quantities[i];
}
else if(quantities[i] > number)
{
return min_value;
}
}
return min_value;
}
else
{
return false;
}
};
答案 6 :(得分:0)
由于Array.reduce
长期存在(even IE9 supports it),因此可以轻松解决此问题。这样,无需先对数组排序(根本不需要数组突变):
var numbers = [20, 25, 30, 35, 5, 10, 15], x = 7;
var output = numbers.reduce(function (prev, curr) {
return Math.abs(curr - x) < Math.abs(prev - x) ? curr : prev
});
console.log(output);
您可以使用箭头功能(但在本例中为no IE support),仅用一行ES6(ECMAScript 2015)语法来解决该问题: >
const numbers = [20, 25, 30, 35, 5, 10, 15], x = 7;
const output = numbers.reduce((prev, curr) => Math.abs(curr - x) < Math.abs(prev - x) ? curr : prev);
console.log(output);
当然,出于灵活性和可重用性,将其作为函数很容易:
const closest = (array, goal) => array.reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
console.log(closest([20, 25, 30, 35, 5, 10, 15], 7));
console.log(closest([20, 25, 30, 35, 5, 10, 15], 8));
console.log(closest([1, 5, 7], -5));
console.log(closest([1, 5, 7], 4));
console.log(closest([1, 5, 7], 20));