Get the closest number from the array

I have a number from minus 1000 to plus 1000, and I have an array with numbers in it. Like this:

[2, 42, 82, 122, 162, 202, 242, 282, 322, 362] 

I want the number that I had to change to the nearest number in the array.

For example, I get 80 as the number I want to get 82 .

+137
javascript arrays
Dec 21 2018-11-11T00:
source share
16 answers

ES5 Version:

 var counts = [4, 9, 15, 6, 2], goal = 5; var closest = counts.reduce(function(prev, curr) { return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev); }); console.log(closest); 
+166
09 Oct '13 at 16:37
source share

Here's the pseudocode that should be converted to any procedural language:

 array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362] number = 112 print closest (number, array) def closest (num, arr): curr = arr[0] foreach val in arr: if abs (num - val) < abs (num - curr): curr = val return curr 

It just works with the absolute differences between the given number and each element of the array and returns you one of them with minimal difference.

For example values:

 number = 112 112 112 112 112 112 112 112 112 112 array = 2 42 82 122 162 202 242 282 322 362 diff = 110 70 30 10 50 90 130 170 210 250 | +-- one with minimal absolute difference. 

As a proof of concept, here is the Python code I used to show this in action:

 def closest (num, arr): curr = arr[0] for index in range (len (arr)): if abs (num - arr[index]) < abs (num - curr): curr = arr[index] return curr array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362] number = 112 print closest (number, array) 



And if you really need it in Javascript, see below the full HTML file that demonstrates the function in action:

 <html> <head></head> <body> <script language="javascript"> function closest (num, arr) { var curr = arr[0]; var diff = Math.abs (num - curr); for (var val = 0; val < arr.length; val++) { var newdiff = Math.abs (num - arr[val]); if (newdiff < diff) { diff = newdiff; curr = arr[val]; } } return curr; } array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; number = 112; alert (closest (number, array)); </script> </body> </html> 



Now keep in mind that there may be opportunities to increase efficiency if, for example, your data is sorted (this can be done from sample data, but you did not explicitly specify this). For example, you can use binary search to find the closest item.

You should also keep in mind that if you do not need to do this many times per second, the increase in efficiency will be mostly imperceptible if your data sets are not much larger.

If you want to try this way (and you can guarantee that the array is sorted in ascending order), this is a good starting point:

 <html> <head></head> <body> <script language="javascript"> function closest (num, arr) { var mid; var lo = 0; var hi = arr.length - 1; while (hi - lo > 1) { mid = Math.floor ((lo + hi) / 2); if (arr[mid] < num) { lo = mid; } else { hi = mid; } } if (num - arr[lo] <= arr[hi] - num) { return arr[lo]; } return arr[hi]; } array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; number = 112; alert (closest (number, array)); </script> </body> </html> 

Mostly used bracketing and checking the average value to reduce the solution space by half for each iteration, the classic O(log N) algorithm, while the sequential search was O(N) :

 0 1 2 3 4 5 6 7 8 9 <- indexes 2 42 82 122 162 202 242 282 322 362 <- values LMHL=0, H=9, M=4, 162 higher, H<-M LMHL=0, H=4, M=2, 82 lower/equal, L<-M LMHL=2, H=4, M=3, 122 higher, H<-M LHL=2, H=3, difference of 1 so exit ^ | H (122-112=10) is closer than L (112-82=30) so choose H 

As already mentioned, this should not matter much for small datasets or for things that don't need to be dazzlingly fast, but this is an option that you might want to consider.

+138
Dec 21 '11 at 4:01
source share

ES6 (2015) Version:

 const counts = [4, 9, 15, 6, 2]; const goal = 5; const output = counts.reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev); console.log(output); 

For reuse, you can use the curry function, which supports placeholders ( http://ramdajs.com/0.19.1/docs/#curry or https://lodash.com/docs#curry ). This gives you more flexibility depending on what you need:

 const getClosest = curry((counts, goal) => { return counts .reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev); }); const closestTo5 = getClosest(_, 5); const closestTo = getClosest([4, 9, 15, 6, 2]); 
+34
Jan 25 '16 at 19:18
source share

Working code as below:

 var array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; function closest(array, num) { var i = 0; var minDiff = 1000; var ans; for (i in array) { var m = Math.abs(num - array[i]); if (m < minDiff) { minDiff = m; ans = array[i]; } } return ans; } console.log(closest(array, 88)); 

+22
Dec 21 '11 at 4:24 a.m.
source share

Works with unsorted arrays

Although there were some good solutions here, JavaScript is a flexible language that provides us with tools to solve problems in various ways. Of course, it all depends on your style. If your code is more functional, you will find a suitable reduction option , i.e.

  arr.reduce(function (prev, curr) { return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev); }); 

However, some may find it difficult to read, depending on their coding style. Therefore, I propose a new way to solve the problem:

  var findClosest = function (x, arr) { var indexArr = arr.map(function(k) { return Math.abs(k - x) }) var min = Math.min.apply(Math, indexArr) return arr[indexArr.indexOf(min)] } findClosest(80, [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]) // Outputs 82 

Unlike other approaches that define the minimum value using Math.min.apply , this Math.min.apply does not require sorting the input arr array. We do not need to care about the indexes or sort them in advance.

I will explain the code line by line for clarity:

  1. arr.map(function(k) { return Math.abs(k - x) }) Creates a new array, essentially storing the absolute values ​​of the given numbers (the number in arr ) minus the input number ( x ). Next we will look for the smallest number (which is also closest to the number you enter)
  2. Math.min.apply(Math, indexArr) This is Math.min.apply(Math, indexArr) way to find the smallest number in the array we just created (nothing more)
  3. arr[indexArr.indexOf(min)] This is perhaps the most interesting part. We found our smallest number, but we are not sure if we should add or subtract the initial number ( x ). This is because we used Math.abs() to find the difference. However, array.map creates (logically) a map of the input array, storing the indices in one place. Therefore, to find the nearest number, we simply return the index of the minimum found in this array indexArr.indexOf(min) .

I created a bin showing this.

+14
09 Oct '16 at 9:51
source share

For sorted arrays (linear search)

All answers are so far focused on searching the entire array. Given that your array is already sorted and you really want only the closest number, this is probably the fastest solution:

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

Please note that the algorithm can be significantly improved, for example, using a binary tree.

+10
Aug 01 '14 at 19:49
source share

This solution uses the existential quantifier ES5 Array#some , which allows you to stop the iteration if the condition is met.

Opposition Array#reduce redund, no need to iterate all elements for a single result.

Inside the callback, the absolute delta between the sought value and the actual item is taken and compared with the last delta. If greater than or equal, the iteration stops because all other values ​​with their deltas are greater than the actual value.

If delta in lastDelta less, then the actual element is assigned to the result, and delta stored in lastDelta .

Finally, lower values ​​are taken with equal deltas, as in Example 22 below, which leads to 2 .

If there is a priority of large values, the delta check should be changed from:

 if (delta >= lastDelta) { 

so that:

 if (delta > lastDelta) { // ^^^ without equal sign 

This will get 22 , the result is 42 (priority of large values).

This function needs sorted values ​​in an array.




Code with priority of lower values:

 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 

Code with priority of large values:

 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 
+6
Dec 12 '16 at 7:58
source share

All solutions are overloaded.

It is as simple as:

 const needle = 5; const haystack = [1, 2, 3, 4, 5, 6, 7, 8, 9]; haystack.sort((a, b) => { return Math.abs(a - needle) - Math.abs(b - needle); }); // 5 
+5
May 16 '19 at 14:46
source share

I do not know if I should answer the old question, but since this message appears primarily in a Google search, I hoped that you would forgive me adding my solution and my 2c here.

Being lazy, I could not believe that the solution for this question would be LOOP, so I searched a little more and returned with a filter function :

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

What all!

+3
Apr 04 '14 at 21:19
source share

My answer to a similar question also takes into account the connections, and it is in plain Javascript, although it does not use binary search, therefore O (N), not O (logN):

 var searchArray= [0, 30, 60, 90]; var element= 33; function findClosest(array,elem){ var minDelta = null; var minIndex = null; for (var i = 0 ; i<array.length; i++){ var delta = Math.abs(array[i]-elem); if (minDelta == null || delta < minDelta){ minDelta = delta; minIndex = i; } //if it is a tie return an array of both values else if (delta == minDelta) { return [array[minIndex],array[i]]; }//if it has already found the closest value else { return array[i-1]; } } return array[minIndex]; } var closest = findClosest(searchArray,element); 

stack overflow

+2
Oct 17 '14 at 16:46
source share

I like the approach from Fusion, but there is a small mistake. How is it right:

  function closest(array, number) { var num = 0; for (var i = array.length - 1; i >= 0; i--) { if(Math.abs(number - array[i]) < Math.abs(number - array[num])){ num = i; } } return array[num]; } 

It is also slightly faster because it uses an improved for loop.

At the end, I wrote my function as follows:

  var getClosest = function(number, array) { var current = array[0]; var difference = Math.abs(number - current); var index = array.length; while (index--) { var newDifference = Math.abs(number - array[index]); if (newDifference < difference) { difference = newDifference; current = array[index]; } } return current; }; 

I tested it with console.time() and is slightly faster than another function.

+2
Mar 01 '16 at 15:33
source share

A slightly modified binary search in the array will work.

0
Dec 21 '11 at 4:00
source share

For a small range, the easiest thing is to have an array of cards, where, for example, the 80th record will have a value of 82 in it to use your example. For a much larger, rarer range, the path is probably a binary search.

With the query language, you can request values ​​at some distance from each side of your input number, and then sort the resulting result list. But SQL does not have a good “next” or “previous” concept to give you a “clean” solution.

0
Dec 21 '11 at 4:01
source share

Another option here has a round range connecting the head to the nose and accepting only the minimum value for a given input. This helped me get the char code values ​​for one of the encryption algorithms.

 function closestNumberInCircularRange(codes, charCode) { return codes.reduce((p_code, c_code)=>{ if(((Math.abs(p_code-charCode) > Math.abs(c_code-charCode)) || p_code > charCode) && c_code < charCode){ return c_code; }else if(p_code < charCode){ return p_code; }else if(p_code > charCode && c_code > charCode){ return Math.max.apply(Math, [p_code, c_code]); } return p_code; }); } 
0
Aug 02 '17 at 5:36 on
source share
 #include <algorithm> #include <iostream> #include <cmath> using namespace std; class CompareFunctor { public: CompareFunctor(int n) { _n = n; } bool operator()(int & val1, int & val2) { int diff1 = abs(val1 - _n); int diff2 = abs(val2 - _n); return (diff1 < diff2); } private: int _n; }; int Find_Closest_Value(int nums[], int size, int n) { CompareFunctor cf(n); int cn = *min_element(nums, nums + size, cf); return cn; } int main() { int nums[] = { 2, 42, 82, 122, 162, 202, 242, 282, 322, 362 }; int size = sizeof(nums) / sizeof(int); int n = 80; int cn = Find_Closest_Value(nums, size, n); cout << "\nClosest value = " << cn << endl; cin.get(); } 
0
May 30 '19 at 9:05
source share

Here is a code snippet to find the closest element to a number from an array in Complexity O (nlog (n)): -

Input: - {1,60,0, -10, 100,87,56} Element: - 56 The closest number in the array: - 60

Source Code (Java):

 package com.algo.closestnumberinarray; import java.util.TreeMap; public class Find_Closest_Number_In_Array { public static void main(String arsg[]) { int array[] = { 1, 60, 0, -10, 100, 87, 69 }; int number = 56; int num = getClosestNumber(array, number); System.out.println("Number is=" + num); } public static int getClosestNumber(int[] array, int number) { int diff[] = new int[array.length]; TreeMap<Integer, Integer> keyVal = new TreeMap<Integer, Integer>(); for (int i = 0; i < array.length; i++) { if (array[i] > number) { diff[i] = array[i] - number; keyVal.put(diff[i], array[i]); } else { diff[i] = number - array[i]; keyVal.put(diff[i], array[i]); } } int closestKey = keyVal.firstKey(); int closestVal = keyVal.get(closestKey); return closestVal; } } 
-four
Apr 03 '18 at 11:51
source share



All Articles