我有一个从- 1000到+ 1000的数我有一个数组,里面都是数字。是这样的:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
我想让我得到的数字变成数组中最接近的数字。
例如,我的数字是80,我希望它是82。
我有一个从- 1000到+ 1000的数我有一个数组,里面都是数字。是这样的:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
我想让我得到的数字变成数组中最接近的数字。
例如,我的数字是80,我希望它是82。
当前回答
ES6
适用于已排序和未排序数组
数字整数和浮点数,字符串欢迎
/**
* Finds the nearest value in an array of numbers.
* Example: nearestValue(array, 42)
*
* @param {Array<number>} arr
* @param {number} val the ideal value for which the nearest or equal should be found
*/
const nearestValue = (arr, val) => arr.reduce((p, n) => (Math.abs(p) > Math.abs(n - val) ? n - val : p), Infinity) + val
例子:
let values = [1,2,3,4,5]
console.log(nearestValue(values, 10)) // --> 5
console.log(nearestValue(values, 0)) // --> 1
console.log(nearestValue(values, 2.5)) // --> 2
values = [100,5,90,56]
console.log(nearestValue(values, 42)) // --> 56
values = ['100','5','90','56']
console.log(nearestValue(values, 42)) // --> 56
其他回答
对于排序数组(线性搜索)
到目前为止,所有答案都集中在搜索整个数组上。 考虑到你的数组已经排序,你真的只想要最近的数字,这可能是最简单的(但不是最快的)解决方案:
var a = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; var target = 90000; /** * Returns the closest number from a sorted array. **/ function closest(arr, target) { if (!(arr) || arr.length == 0) return null; if (arr.length == 1) return arr[0]; for (var i = 1; i < arr.length; i++) { // As soon as a number bigger than target is found, return the previous or current // number depending on which has smaller difference to the target. if (arr[i] > target) { var p = arr[i - 1]; var c = arr[i] return Math.abs(p - target) < Math.abs(c - target) ? p : c; } } // No number in array is bigger so return the last. return arr[arr.length - 1]; } // Trying it out console.log(closest(a, target));
请注意,该算法可以大大改进,例如使用二叉树。
你可以使用下面的逻辑找到最接近的数字,而不使用reduce函数
let arr = [0, 80, 10, 60, 20, 50, 0, 100, 80, 70, 1];
const n = 2;
let closest = -1;
let closeDiff = -1;
for (let i = 0; i < arr.length; i++) {
if (Math.abs(arr[i] - n) < closeDiff || closest === -1) {
closeDiff = Math.abs(arr[i] - n);
closest = arr[i];
}
}
console.log(closest);
这个解决方案使用ES5存在量词数组#some,它允许在满足条件时停止迭代。
与array# reduce相反,它不需要为一个结果迭代所有元素。
在回调中,获取搜索值与实际项之间的绝对增量,并与最后的增量进行比较。如果大于或等于,迭代将停止,因为所有其他具有delta的值都大于实际值。
如果回调中的增量较小,则实际的项被分配给结果,增量保存在lastDelta中。
最后,取具有相等增量的较小值,如下面22的示例,结果为2。
如果有更大的优先级值,delta检查必须从以下更改:
if (delta >= lastDelta) {
to:
if (delta > lastDelta) {
// ^^^ without equal sign
这将得到22,结果为42(较大值的优先级)。
这个函数需要数组中排序的值。
优先级较小的代码:
function closestValue(array, value) { var result, lastDelta; array.some(function (item) { var delta = Math.abs(value - item); if (delta >= lastDelta) { return true; } result = item; lastDelta = delta; }); return result; } var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; console.log(21, closestValue(data, 21)); // 2 console.log(22, closestValue(data, 22)); // 2 smaller value console.log(23, closestValue(data, 23)); // 42 console.log(80, closestValue(data, 80)); // 82
优先级较高的代码:
function closestValue(array, value) { var result, lastDelta; array.some(function (item) { var delta = Math.abs(value - item); if (delta > lastDelta) { return true; } result = item; lastDelta = delta; }); return result; } var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; console.log(21, closestValue(data, 21)); // 2 console.log(22, closestValue(data, 22)); // 42 greater value console.log(23, closestValue(data, 23)); // 42 console.log(80, closestValue(data, 80)); // 82
如果数组像你的例子中那样排序,你可以使用二进制搜索来获得O(log n)更好的时间复杂度。
const myArray = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; const binaryClosestIdx = (arr, target) => { let start = 0; let end = arr.length - 1; let mid = Math.floor((start + end) / 2); while (1) { if (arr[mid] === target) { return mid; } else if (start >= end) { break; } else if (arr[mid] > target) { end = mid - 1; } else { start = mid + 1; } mid = Math.floor((start + end) / 2); } // Return the closest between the last value checked and it's surrounding neighbors const first = Math.max(mid - 1, 0); const neighbors = arr.slice(first, mid + 2); const best = neighbors.reduce((b, el) => Math.abs(el - target) < Math.abs(b - target) ? el : b); return first + neighbors.indexOf(best); } const closestValue = myArray[binaryClosestIdx(myArray, 80)]; console.log(closestValue);
工作原理:
它将目标值与数组的中间元素进行比较。如果中间的元素更大,我们可以忽略它后面的每个元素,因为它们会更大。同样,如果中间的元素更小,我们可以忽略它之前的所有元素。 如果找到了目标值,则返回它,否则将最后测试的值与其周围的相邻值进行比较,因为最近的值只能在这3个值之间。
我不知道我是否应该回答一个老问题,但由于这篇文章首先出现在谷歌搜索中,我希望你能原谅我在这里添加我的解决方案和我的2c。
由于懒惰,我无法相信这个问题的解决方案会是一个LOOP,所以我搜索了更多,并返回了过滤器函数:
var myArray = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
var myValue = 80;
function BiggerThan(inArray) {
return inArray > myValue;
}
var arrBiggerElements = myArray.filter(BiggerThan);
var nextElement = Math.min.apply(null, arrBiggerElements);
alert(nextElement);
就这些!