Related
var myArr = [1,2,3,4,5,6,7,8,9,10];
function even(num) {
var newArr = [];
for (var i=1; i<num.length; i++) {
if (num[i] % 2 === 0) {
newArr.push(num[i]);
}
}
return newArr;
}
console.log(even(myArr));
My function throws an exception when called. How can I rewrite or refactor the above code to return the first 5 positive numbers?
You can create it this way.
var myArr = [1,2,0,3,4,-6,5,-3,88,21,-6,5,6,7,8,9,10];
let evens = myArr.filter(x => x > 0 && x % 2 == 0).slice(0, 5);
console.log(evens)
First off, your code appears to work. Can you give an example of the error that is occurring? Second off, if you want a function that returns an array of the first n positive, even integers, you can write something like this.
function firstEven(count) {
var response = []; // Create the response list
for(var i=0;i<count;i++) { // Loop for number of even numbers you want
response.push((i + 1) * 2); // *2 skips every two numbers, and +1 shifts the number to even
}
return response
}
However, if you want to just filter out all odd numbers from an array, you can do the following.
var myArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var myEvens = myArr.filter(function(myNum) { // Filter runs the function for every value in the array, and (if the function returns false) it removed that value
return (myNum % 2) == 0;
});
Feel free to ask if you have any questions!
2 others differnts ways
const myArr = [1,2,3,4,-6,5,-3,88,21,-6,5,6,7,8,9,10];
const even_1 = arr => arr.filter(x=>(x>=0 && !(x&1))).slice(0,5)
const even_2 = arr =>
{
let r = []
for(x of arr)
if (x>=0 && !(x&1)) // test2 = boolean AND on bit zero
{
r.push(x);
if (r.length >= 5) break;
}
return r
}
console.log('even 1:', even_1(myArr).join(','))
console.log('even 2:', even_2(myArr).join(','))
One suggestion:
var myArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
function even(numbersArray) {
var first5EvenNums = [];
for (const num of numbersArray) {
if (first5EvenNums.length >= 5) break;
if (num % 2 === 0) {
first5EvenNums.push(num);
}
}
return first5EvenNums;
}
console.log(even(myArr));
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div id="test"></div>
<script>
var myArr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
function even(num){
var newArr = [];
for (var i=1; i<num.length; i++){
if (num[i] % 2 === 0)
{
newArr.push(num[i]);
if(newArr.length == 5){
return newArr;
}
}
}
return newArr;
};
$("#test").text(even(myArr));
</script>
This return first 5 positive number in 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 that the number I've got changes to the nearest number of the array.
For example I get 80 as number I want it to get 82.
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);
Here's the pseudo-code which should be convertible into 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 simply works out the absolute differences between the given number and each array element and gives you back one of the ones with the minimal difference.
For the 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's 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 for a complete HTML file which 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 there may be scope for improved efficiency if, for example, your data items are sorted (that could be inferred from the sample data but you don't explicitly state it). You could, for example, use a binary search to find the closest item.
You should also keep in mind that, unless you need to do it many times per second, the efficiency improvements will be mostly unnoticable unless your data sets get much larger.
If you do want to try it that way (and can guarantee 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>
It basically uses bracketing and checking of the middle value to reduce the solution space by half for each iteration, a classic O(log N) algorithm whereas the sequential search above 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
L M H L=0, H=9, M=4, 162 higher, H<-M
L M H L=0, H=4, M=2, 82 lower/equal, L<-M
L M H L=2, H=4, M=3, 122 higher, H<-M
L H L=2, H=3, difference of 1 so exit
^
|
H (122-112=10) is closer than L (112-82=30) so choose H
As stated, that shouldn't make much of a difference for small datasets or for things that don't need to be blindingly fast, but it's an option you may want to consider.
ES6 (ECMAScript 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 reusability you can wrap in a curry function that supports placeholders (http://ramdajs.com/0.19.1/docs/#curry or https://lodash.com/docs#curry). This gives lots of 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 closestToFive = getClosest(_, 5);
const output = closestToFive([4, 9, 15, 6, 2]);
console.log(output);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
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));
Works with unsorted arrays
While there were some good solutions posted here, JavaScript is a flexible language that gives us tools to solve a problem in many different ways.
It all comes down to your style, of course. If your code is more functional, you'll find the reduce variation suitable, i.e.:
arr.reduce(function (prev, curr) {
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
});
However, some might find that hard to read, depending on their coding style. Therefore I propose a new way of solving 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
Contrary to other approaches finding the minimum value using Math.min.apply, this one doesn't require the input array arr to be sorted. We don't need to care about the indexes or sort it beforehand.
I'll explain the code line by line for clarity:
arr.map(function(k) { return Math.abs(k - x) }) Creates a new array, essentially storing the absolute values of the given numbers (number in arr) minus the input number (x). We'll look for the smallest number next (which is also the closest to the input number)
Math.min.apply(Math, indexArr) This is a legit way of finding the smallest number in the array we've just created before (nothing more to it)
arr[indexArr.indexOf(min)] This is perhaps the most interesting part. We have found our smallest number, but we're not sure if we should add or subtract the initial number (x). That's because we used Math.abs() to find the difference. However, array.map creates (logically) a map of the input array, keeping the indexes in the same place. Therefore, to find out the closest number we just return the index of the found minimum in the given array indexArr.indexOf(min).
I've created a bin demonstrating it.
All of the solutions are over-engineered.
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);
})[0];
// 5
For sorted arrays (linear search)
All answers so far concentrate on searching through the whole array.
Considering your array is sorted already and you really only want the nearest number this is probably the easiest (but not 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));
Note that the algorithm can be vastly improved e.g. using a binary tree.
ES6
Works with sorted and unsorted arrays
Numbers Integers and Floats, Strings welcomed
/**
* 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
Examples:
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
This solution uses ES5 existential quantifier Array#some, which allows to stop the iteration, if a condition is met.
Opposit of Array#reduce, it does not need to iterate all elements for one result.
Inside the callback, an absolute delta between the searched value and actual item is taken and compared with the last delta. If greater or equal, the iteration stops, because all other values with their deltas are greater than the actual value.
If the delta in the callback is smaller, then the actual item is assigned to the result and the delta is saved in lastDelta.
Finally, smaller values with equal deltas are taken, like in the below example of 22, which results in 2.
If there is a priority of greater values, the delta check has to be changed from:
if (delta >= lastDelta) {
to:
if (delta > lastDelta) {
// ^^^ without equal sign
This would get with 22, the result 42 (Priority of greater values).
This function needs sorted values in the array.
Code with priority of smaller 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 greater 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
Other answers suggested the you would need to iterate through the entire array:
calculate the deviation for each element
keep track of the smallest deviation and its element
finally, after iterating through the entire array, return that element with that smallest deviation.
If the array is already sorted, that does not make sense. There is no need to calculate all deviations. e.g. in an ordered collection of 1 million elements, you only need to calculate ~19 deviations (at most) to find your match. You can accomplish this with a binary-search approach:
function findClosestIndex(arr, element) {
let from = 0, until = arr.length - 1
while (true) {
const cursor = Math.floor((from + until) / 2);
if (cursor === from) {
const diff1 = element - arr[from];
const diff2 = arr[until] - element;
return diff1 <= diff2 ? from : until;
}
const found = arr[cursor];
if (found === element) return cursor;
if (found > element) {
until = cursor;
} else if (found < element) {
from = cursor;
}
}
}
Result:
console.log(findClosestIndex([0, 1, 2, 3.5, 4.5, 5], 4));
// output: 3
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], 4));
// output: 4
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], 90));
// output: 5
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], -1));
// output: 0
A simpler way with O(n) time complexity is to do this in one iteration of the array. This method is intended for unsorted arrays.
Following is a javascript example, here from the array we find the number which is nearest to "58".
var inputArr = [150, 5, 200, 50, 30];
var search = 58;
var min = Math.min();
var result = 0;
for(i=0;i<inputArr.length;i++) {
let absVal = Math.abs(search - inputArr[i])
if(min > absVal) {
min=absVal;
result = inputArr[i];
}
}
console.log(result); //expected output 50 if input is 58
This will work for positive, negative, decimal numbers as well.
Math.min() will return Infinity.
The result will store the value nearest to the search element.
I don't know if I'm supposed to answer an old question, but as this post appears first on Google searches, I hoped that you would forgive me adding my solution & my 2c here.
Being lazy, I couldn't believe that the solution for this question would be a LOOP, so I searched a bit more and came back with 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);
That's all !
My answer to a similar question is accounting for ties too and it is in plain Javascript, although it doesn't use binary search so it is O(N) and 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);
https://stackoverflow.com/a/26429528/986160
I like the approach from Fusion, but there's a small error in it. Like that it is correct:
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 it also a bit faster because it uses the improved for loop.
At the end I wrote my function like this:
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 it is slightly faster than the other function.
The most efficient would be a binary search. However even simple solutions can exit when the next number is a further match from the current. Nearly all solutions here are not taking into account that the array is ordered and iterating though the whole thing :/
const closest = (orderedArray, value, valueGetter = item => item) =>
orderedArray.find((item, i) =>
i === orderedArray.length - 1 ||
Math.abs(value - valueGetter(item)) < Math.abs(value - valueGetter(orderedArray[i + 1])));
var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
console.log('21 -> 2', closest(data, 21) === 2);
console.log('22 -> 42', closest(data, 22) === 42); // equidistant between 2 and 42, select highest
console.log('23 -> 42', closest(data, 23) === 42);
console.log('80 -> 82', closest(data, 80) === 82);
This can be run on non-primitives too e.g. closest(data, 21, item => item.age)
Change find to findIndex to return the index in the array.
If the array is sorted like in your example, you can use a Binary Search for a better time complexity of 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);
How it works :
It compares the target value to the middle element of the array. If the middle element is bigger we can ignore every element after it as they are going to be even bigger. The same goes if the middle element is smaller, we can ignore every element before it.
If the target value is found we return it, otherwise we compare the last value tested with its surrounding neighbors as the closest value can only be between those 3 values.
Another variant here we have circular range connecting head to toe and accepts only min value to given input. This had helped me get char code values for one of the encryption algorithm.
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;
});
}
To Find Two Closest Number in array
function findTwoClosest(givenList, goal) {
var first;
var second;
var finalCollection = [givenList[0], givenList[1]];
givenList.forEach((item, firtIndex) => {
first = item;
for (let i = firtIndex + 1; i < givenList.length; i++) {
second = givenList[i];
if (first + second < goal) {
if (first + second > finalCollection[0] + finalCollection[1]) {
finalCollection = [first, second];
}
}
}
});
return finalCollection;
}
var counts = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
var goal = 80;
console.log(findTwoClosest(counts, goal));
You can use below logic to find closest number without using reduce function
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);
#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();
}
For a small range, the simplest thing is to have a map array, where, eg, the 80th entry would have the value 82 in it, to use your example. For a much larger, sparse range, probably the way to go is a binary search.
With a query language you could query for values some distance either side of your input number and then sort through the resulting reduced list. But SQL doesn't have a good concept of "next" or "previous", to give you a "clean" solution.
Create a function called biggestNumberInArray().
That takes an array as a parameter and returns the biggest number.
Here is an array
const array = [-1, 0, 3, 100, 99, 2, 99]
What I try in my JavaScript code:
function biggestNumberInArray(arr) {
for (let i = 0; i < array.length; i++) {
for(let j=1;j<array.length;j++){
for(let k =2;k<array.length;k++){
if(array[i]>array[j] && array[i]>array[k]){
console.log(array[i]);
}
}
}
}
}
It returns 3 100 99.
I want to return just 100 because it is the biggest number.
Is there a better way to use loops to get the biggest value?
Using three different JavaScript loops to achieve this (for, forEach, for of, for in).
You can use three of them to accomplish it.
Some ES6 magic for you, using the spread syntax:
function biggestNumberInArray(arr) {
const max = Math.max(...arr);
return max;
}
Actually, a few people have answered this question in a more detailed fashion than I do, but I would like you to read this if you are curious about the performance between the various ways of getting the largest number in an array.
zer00ne's answer should be better for simplicity, but if you still want to follow the for-loop way, here it is:
function biggestNumberInArray (arr) {
// The largest number at first should be the first element or null for empty array
var largest = arr[0] || null;
// Current number, handled by the loop
var number = null;
for (var i = 0; i < arr.length; i++) {
// Update current number
number = arr[i];
// Compares stored largest number with current number, stores the largest one
largest = Math.max(largest, number);
}
return largest;
}
There are multiple ways.
Using Math max function
let array = [-1, 10, 30, 45, 5, 6, 89, 17];
console.log(Math.max(...array))
Using reduce
let array = [-1, 10, 30, 45, 5, 6, 89, 17];
console.log(array.reduce((element,max) => element > max ? element : max, 0));
Implement our own function
let array = [-1, 10, 30, 45, 5, 6, 89, 17];
function getMaxOutOfAnArray(array) {
let maxNumber = -Infinity;
array.forEach(number => { maxNumber = number > maxNumber ? number : maxNumber; })
console.log(maxNumber);
}
getMaxOutOfAnArray(array);
The simplest way is using Math.max.apply:
const array = [-1,0,3,100, 99, 2, 99];
function biggestNumberInArray(arr) {
return Math.max.apply(Math, arr);
}
console.log(biggestNumberInArray(array));
If you really want to use a for loop, you can do it using the technique from this answer:
const array = [-1,0,3,100, 99, 2, 99];
function biggestNumberInArray(arr) {
var m = -Infinity,
i = 0,
n = arr.length;
for (; i != n; ++i) {
if (arr[i] > m) {
m = arr[i];
}
}
return m;
}
console.log(biggestNumberInArray(array));
And you could also use reduce:
const array = [-1,0,3,100, 99, 2, 99];
function biggestNumberInArray(array) {
return array.reduce((m, c) => c > m ? c : m);
}
console.log(biggestNumberInArray(array));
I think you misunderstand how loops are used - there is no need to have three nested loops. You can iterate through the array with a single loop, keeping track of the largest number in a variable, then returning the variable at the end of the loop.
function largest(arr) {
var largest = arr[0]
arr.forEach(function(i) {
if (i > largest){
largest = i
}
}
return largest;
}
Of course you can do this much more simply:
Math.max(...arr)
but the question does ask for a for loop implementation.
This is best suited to some functional programming and using a reduce, for loops are out of favour these days.
const max = array => array && array.length ? array.reduce((max, current) => current > max ? current : max) : undefined;
console.log(max([-1, 0, 3, 100, 99, 2, 99]));
This is 70% more performant than Math.max https://jsperf.com/max-vs-reduce/1
Another visual way is to create a variable called something like maxNumber, then check every value in the array, and if it is greater than the maxNumber, then the maxNumber now = that value.
const array = [-1,0,3,100, 99, 2, 99];
function biggestNumberInArray(arr) {
let maxNumber;
for(let i = 0; i < arr.length; i++){
if(!maxNumber){ // protect against an array of values less than 0
maxNumber = arr[i]
}
if(arr[i] > maxNumber){
maxNumber = arr[i];
}
}
return maxNumber
}
console.log(biggestNumberInArray(array));
I hope this helps :)
var list = [12,34,11,10,34,68,5,6,2,2,90];
var length = list.length-1;
for(var i=0; i<length; i++){
for(j=0; j<length; j++){
if(list[j]>list[j+1]){
[ list[j] , list[j+1] ] = [ list[j+1] , list[j] ];
}
}
}
console.log(list[list.length-1]);
You Can try My codes to find the highest number form array using for loop.
function largestNumber(number){
let max = number[0];
for(let i = 0; i < number.length; i++){
let element = number[i];
if(element > max){
max = element;
}
}
return max;
}
let arrayNum= [22,25,40,60,80,100];
let result = largestNumber(arrayNum);
console.log('The Highest Number is: ',result);
let arr = [1,213,31,42,21];
let max = 0;
for(let i = 0; i < arr.length; i++) {
if(arr[i] > max) {
max = arr[i]
}
}
console.log(max)
There are multiple ways.
way - 1 | without for loop
const data = [-1, 0, 3, 100, 99, 2, 99];
// way - 1 | without for loop
const maxValue = Math.max(...data);
const maxIndex = data.indexOf(maxValue);
console.log({ maxValue, maxIndex }); // { maxValue: 100, maxIndex: 3 }
way - 2 | with for loop
const data = [-1, 0, 3, 100, 99, 2, 99];
// way - 2 | with for loop
let max = data[0];
for (let i = 0; i < data.length; i++) {
if (data[i] > max) {
max = data[i];
}
}
console.log(max); // 100
THis is the simple function to find the biggest number in array with for loop.
// Input sample data to the function
var arr = [-1, 0, 3, 100, 99, 2, 99];
// Just to show the result
console.log(findMax(arr));
// Function to find the biggest integer in array
function findMax(arr) {
// size of array
let arraySize = arr.length;
if (arraySize > 0) {
// Initialize variable with first index of array
var MaxNumber = arr[0];
for (var i = 0; i <= arraySize; i++) {
// if new number is greater than previous number
if (arr[i] > MaxNumber) {
// then assign greater number to variable
MaxNumber = arr[i];
}
}
// return biggest number
return MaxNumber;
} else {
return 0;
}
}
You can try this if you want to practice functions
const numbs = [1, 2, 4, 5, 6, 7, 8, 34];
let max = (arr) => {
let max = arr[0];
for (let i of arr) {
if (i > max) {
max = i;
}
}
return max;
};
let highestNumb = max(numbs);
console.log(highestNumb);
const array = [-1, 0, 3, 100, 99, 2, 99]
let longest = Math.max(...array);
what about this
const array = [1, 32, 3, 44, 5, 6]
console.time("method-test")
var largestNum = array[0]
for(var i = 1; i < array.length; i++) {
largestNum = largestNum > array[i] ? largestNum : array[i]
}
console.log(largestNum)
console.timeEnd("method-test")
I am using Math.min to get the smallest number out of an array of numbers. However, I also need to get the second smallest number as well. Wondering if there is a way to do this using Math.min as well, otherwise looking for the best way to get this number.
Here's what I have:
var arr = [15, 37, 9, 21, 55];
var min = Math.min.apply(null, arr.filter(Boolean));
var secondMin; // Get second smallest number from array here
console.log('Smallest number: ' + min);
console.log('Second smallest number: ' + secondMin);
just to make that thread completed: the fastest way is to iterate all the elements just like you can do to find minimum. But up to your needs there will be two variables used: first minimum (candidate) and second one.
This logic is O(N) while sorting approach is O(N lg(N)).
But maybe you shouldn't care if this is just for practice.
In case repeatition should be processed as independant value(just like it would be for .sort(...)[1]) then it should <= be used instead of <.
var arr = [15, 37, 9, 21, 55];
var min = Infinity, secondMin = Infinity;
for (var i= 0; i< arr.length; i++) {
if (arr[i]< min) {
secondMin = min;
min = arr[i];
} else if (arr[i]< secondMin) {
secondMin = arr[i];
}
}
console.log('Smallest number: ' + min);
console.log('Second smallest number: ' + secondMin);
I see you are using Array.filter (but why?) on your first min. So, if we are using ES6 features you can find the second lowest value by first removing min from the array.
var secondMin = Math.min.apply(null, arr.filter(n => n != min));
edit: for clarity, unless you are doing something very clever with Array.filter(Boolean) while calculating the first min, you should just pass it the array without filtering:
var min = Math.min.apply(null, arr);
If you are not worried about performance you could simply sort the array.
arr.sort(function(a, b) {
return a - b;
});
#skyboyer provides what is probably the fastest algorithm for finding the two smallest elements. Another type algorithm that runs in O(n) time is selection (in the general comp-sci definition, not how it is normally used in JavaScript), which will find the kth smallest element of an array and separate the elements into those larger and those smaller than the kth.
Even though most partitioning selection algorithms (quickselect, Floyd-Rivest, introselect) run in O(n) time, #skyboyer's answer will be faster because of the specific nature of the partition you are looking for, and because all those algorithms come with a heavy constant factor.
There is a javascript library implementing Floyd-Rivest, but named quickselect that can do the partitioning for you, in place:
quickselect(arr, 1)
arr will be rearranged so that arr[0] is the minimum, arr[1] is the second smallest element, and the remaining elements are in some arbitrary order.
ES6 solution with reduce (very performant) 🚀
const A = [8, 24, 3, 20, 1, 17]
const min = Math.min(...A)
const secondMin = A.reduce((pre, cur) => (cur < pre && cur !== min) ? cur : pre
, Infinity)
console.log(min, secondMin)
This the #skyboyer version that will handle repeats correctly:
function secondSmallest(x) {
if (x.length < 2) return 0;
let first = Number.MAX_VALUE;
let second = Number.MAX_VALUE;
for (let i = 0; i < x.length; i++) {
let current = x[i];
if (current < first) {
second = first;
first = current;
} else if (current < second && current !== first) {
second = current;
}
}
return second;
}
console.log(secondSmallest([1, 1, 1, 1, 2]));
console.log(secondSmallest([1, 2, 1, 1, 1]));
console.log(secondSmallest([6, 3, 4, 8, 4, 5]));
var arr=[1,1,1,1,1,-1,-2];
var firstmin=arr[0];
var secondmin=arr[1];
for(i=0;i<=arr.length;i++){
if(arr[i]<firstmin){
secondmin=firstmin;
firstmin=arr[i];
}else if(i>=1 && arr[i]<secondmin) {
secondmin=arr[i];
}
}
console.log(firstmin);
console.log(secondmin);`
var arr=[1,0,-1,-2,-8,5];
var firstmin=arr[0];
var secondmin=arr[1];
for(i=0;i<=arr.length;i++) {
if(arr[i]<firstmin){
secondmin=firstmin;
firstmin=arr[i];
}
else if(i>=1 && arr[i]<secondmin) {
secondmin=arr[i];
}
}
console.log(firstmin);
console.log(secondmin);
var arr = [15, 37, 9, 21, 55];
var min = Infinity, secondMin = Infinity;
for (var i= 0; i< arr.length; i++) {
if (arr[i]< min) {
secondMin = min;
min = arr[i];
} else if (arr[i]< secondMin) {
secondMin = arr[i];
}
}
console.log('Smallest number: ' + min);
console.log('Second smallest number: ' + secondMin);
A recursive approach with ternary operators would look like this. If the array has duplicates it would give you a non duplicated second min.
For example if you have have [1, 1, 2] the second min would be 2 not 1.
function findMinimums(arr, min, secondMin, i) {
if (arr.length === i) {
return {
min,
secondMin
}
}
return findMinimums(
arr,
min = arr[i] < min ? arr[i] : min,
arr[i] < secondMin && min !== arr[i] ? arr[i] : secondMin,
++i
)
}
const arr = [5, 34, 5, 1, 6, 7, 9, 2, 1];
console.log(findMinimums(arr, arr[0], arr[1], 0))
var arr = [15, 37, 9, 21, 55];
const [secondMin, min] = arr.sort((a,b) => b - a).slice(-2)
console.log('Smallest number: ' + min);
console.log('Second smallest number: ' + secondMin);
function secondSmallest(arr){
let firstSmallest = Infinity, secondSmallest = Infinity;
// if the length is 1; return the element
if(arr.length == 1){
return arr[0]
}
for (let i= 0; i< arr.length; i++) {
if (arr[i]< firstSmallest) {
secondSmallest = firstSmallest;
firstSmallest = arr[i];
} else if (arr[i]< secondSmallest) {
secondSmallest = arr[i];
}
}
console.log(firstSmallest, secondSmallest)
return secondSmallest
}
function findTwoSmallestNumbersFromArray(num) {
let min = Math.min(...num)
let secondMin = Math.min(...num.filter(numbers => !min.toString().includes(numbers)))
console.log(min, secondMin)
}
Yes, it's possible. But rather than directly using Math.min() we have to use Math.min.apply(), as we know Math.min() wouldn't take an array. Here's the solution which will work even if there's duplicates of smallest number in the array.
const findSecondSmallest = function (arr) {
const smallest = Math.min.apply(null, arr);
/*
To remove duplicates too I compared the smallest number through loop.
Otherwise You can direcly set the value of smallest element to 'Infinity'
like this-
arr[arr.indexOf(smallest)] = Infinity;
*/
for (let i = 0; i < arr.length; i++) {
if (smallest === arr[i]) {
arr[i] = Infinity;
}
}
const secondSmallest = Math.min.apply(null, arr);
return secondSmallest;
};
console.log(findSecondSmallest([3, 3, 3, 5, 5, 7, 9, 11, 13])); //5
The Best way to get the second minimum value from an array.
let array = [5, 8, 3, 8, 2, 6, 7, 10, 2];
let minValue = Math.min(...array);
let secondMinVAlue = Math.min(...array.filter((v) => v !== minValue));
console.log(secondMinVAlue);
let num = [4,12,99,1,3,123,5];
let sort = num.sort((a,b) => {return a-b})
console.log(sort[1])
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 that the number I've got changes to the nearest number of the array.
For example I get 80 as number I want it to get 82.
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);
Here's the pseudo-code which should be convertible into 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 simply works out the absolute differences between the given number and each array element and gives you back one of the ones with the minimal difference.
For the 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's 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 for a complete HTML file which 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 there may be scope for improved efficiency if, for example, your data items are sorted (that could be inferred from the sample data but you don't explicitly state it). You could, for example, use a binary search to find the closest item.
You should also keep in mind that, unless you need to do it many times per second, the efficiency improvements will be mostly unnoticable unless your data sets get much larger.
If you do want to try it that way (and can guarantee 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>
It basically uses bracketing and checking of the middle value to reduce the solution space by half for each iteration, a classic O(log N) algorithm whereas the sequential search above 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
L M H L=0, H=9, M=4, 162 higher, H<-M
L M H L=0, H=4, M=2, 82 lower/equal, L<-M
L M H L=2, H=4, M=3, 122 higher, H<-M
L H L=2, H=3, difference of 1 so exit
^
|
H (122-112=10) is closer than L (112-82=30) so choose H
As stated, that shouldn't make much of a difference for small datasets or for things that don't need to be blindingly fast, but it's an option you may want to consider.
ES6 (ECMAScript 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 reusability you can wrap in a curry function that supports placeholders (http://ramdajs.com/0.19.1/docs/#curry or https://lodash.com/docs#curry). This gives lots of 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 closestToFive = getClosest(_, 5);
const output = closestToFive([4, 9, 15, 6, 2]);
console.log(output);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
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));
Works with unsorted arrays
While there were some good solutions posted here, JavaScript is a flexible language that gives us tools to solve a problem in many different ways.
It all comes down to your style, of course. If your code is more functional, you'll find the reduce variation suitable, i.e.:
arr.reduce(function (prev, curr) {
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
});
However, some might find that hard to read, depending on their coding style. Therefore I propose a new way of solving 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
Contrary to other approaches finding the minimum value using Math.min.apply, this one doesn't require the input array arr to be sorted. We don't need to care about the indexes or sort it beforehand.
I'll explain the code line by line for clarity:
arr.map(function(k) { return Math.abs(k - x) }) Creates a new array, essentially storing the absolute values of the given numbers (number in arr) minus the input number (x). We'll look for the smallest number next (which is also the closest to the input number)
Math.min.apply(Math, indexArr) This is a legit way of finding the smallest number in the array we've just created before (nothing more to it)
arr[indexArr.indexOf(min)] This is perhaps the most interesting part. We have found our smallest number, but we're not sure if we should add or subtract the initial number (x). That's because we used Math.abs() to find the difference. However, array.map creates (logically) a map of the input array, keeping the indexes in the same place. Therefore, to find out the closest number we just return the index of the found minimum in the given array indexArr.indexOf(min).
I've created a bin demonstrating it.
All of the solutions are over-engineered.
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);
})[0];
// 5
For sorted arrays (linear search)
All answers so far concentrate on searching through the whole array.
Considering your array is sorted already and you really only want the nearest number this is probably the easiest (but not 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));
Note that the algorithm can be vastly improved e.g. using a binary tree.
ES6
Works with sorted and unsorted arrays
Numbers Integers and Floats, Strings welcomed
/**
* 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
Examples:
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
This solution uses ES5 existential quantifier Array#some, which allows to stop the iteration, if a condition is met.
Opposit of Array#reduce, it does not need to iterate all elements for one result.
Inside the callback, an absolute delta between the searched value and actual item is taken and compared with the last delta. If greater or equal, the iteration stops, because all other values with their deltas are greater than the actual value.
If the delta in the callback is smaller, then the actual item is assigned to the result and the delta is saved in lastDelta.
Finally, smaller values with equal deltas are taken, like in the below example of 22, which results in 2.
If there is a priority of greater values, the delta check has to be changed from:
if (delta >= lastDelta) {
to:
if (delta > lastDelta) {
// ^^^ without equal sign
This would get with 22, the result 42 (Priority of greater values).
This function needs sorted values in the array.
Code with priority of smaller 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 greater 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
Other answers suggested the you would need to iterate through the entire array:
calculate the deviation for each element
keep track of the smallest deviation and its element
finally, after iterating through the entire array, return that element with that smallest deviation.
If the array is already sorted, that does not make sense. There is no need to calculate all deviations. e.g. in an ordered collection of 1 million elements, you only need to calculate ~19 deviations (at most) to find your match. You can accomplish this with a binary-search approach:
function findClosestIndex(arr, element) {
let from = 0, until = arr.length - 1
while (true) {
const cursor = Math.floor((from + until) / 2);
if (cursor === from) {
const diff1 = element - arr[from];
const diff2 = arr[until] - element;
return diff1 <= diff2 ? from : until;
}
const found = arr[cursor];
if (found === element) return cursor;
if (found > element) {
until = cursor;
} else if (found < element) {
from = cursor;
}
}
}
Result:
console.log(findClosestIndex([0, 1, 2, 3.5, 4.5, 5], 4));
// output: 3
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], 4));
// output: 4
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], 90));
// output: 5
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], -1));
// output: 0
A simpler way with O(n) time complexity is to do this in one iteration of the array. This method is intended for unsorted arrays.
Following is a javascript example, here from the array we find the number which is nearest to "58".
var inputArr = [150, 5, 200, 50, 30];
var search = 58;
var min = Math.min();
var result = 0;
for(i=0;i<inputArr.length;i++) {
let absVal = Math.abs(search - inputArr[i])
if(min > absVal) {
min=absVal;
result = inputArr[i];
}
}
console.log(result); //expected output 50 if input is 58
This will work for positive, negative, decimal numbers as well.
Math.min() will return Infinity.
The result will store the value nearest to the search element.
I don't know if I'm supposed to answer an old question, but as this post appears first on Google searches, I hoped that you would forgive me adding my solution & my 2c here.
Being lazy, I couldn't believe that the solution for this question would be a LOOP, so I searched a bit more and came back with 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);
That's all !
My answer to a similar question is accounting for ties too and it is in plain Javascript, although it doesn't use binary search so it is O(N) and 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);
https://stackoverflow.com/a/26429528/986160
I like the approach from Fusion, but there's a small error in it. Like that it is correct:
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 it also a bit faster because it uses the improved for loop.
At the end I wrote my function like this:
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 it is slightly faster than the other function.
The most efficient would be a binary search. However even simple solutions can exit when the next number is a further match from the current. Nearly all solutions here are not taking into account that the array is ordered and iterating though the whole thing :/
const closest = (orderedArray, value, valueGetter = item => item) =>
orderedArray.find((item, i) =>
i === orderedArray.length - 1 ||
Math.abs(value - valueGetter(item)) < Math.abs(value - valueGetter(orderedArray[i + 1])));
var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
console.log('21 -> 2', closest(data, 21) === 2);
console.log('22 -> 42', closest(data, 22) === 42); // equidistant between 2 and 42, select highest
console.log('23 -> 42', closest(data, 23) === 42);
console.log('80 -> 82', closest(data, 80) === 82);
This can be run on non-primitives too e.g. closest(data, 21, item => item.age)
Change find to findIndex to return the index in the array.
If the array is sorted like in your example, you can use a Binary Search for a better time complexity of 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);
How it works :
It compares the target value to the middle element of the array. If the middle element is bigger we can ignore every element after it as they are going to be even bigger. The same goes if the middle element is smaller, we can ignore every element before it.
If the target value is found we return it, otherwise we compare the last value tested with its surrounding neighbors as the closest value can only be between those 3 values.
Another variant here we have circular range connecting head to toe and accepts only min value to given input. This had helped me get char code values for one of the encryption algorithm.
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;
});
}
To Find Two Closest Number in array
function findTwoClosest(givenList, goal) {
var first;
var second;
var finalCollection = [givenList[0], givenList[1]];
givenList.forEach((item, firtIndex) => {
first = item;
for (let i = firtIndex + 1; i < givenList.length; i++) {
second = givenList[i];
if (first + second < goal) {
if (first + second > finalCollection[0] + finalCollection[1]) {
finalCollection = [first, second];
}
}
}
});
return finalCollection;
}
var counts = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
var goal = 80;
console.log(findTwoClosest(counts, goal));
You can use below logic to find closest number without using reduce function
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);
#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();
}
For a small range, the simplest thing is to have a map array, where, eg, the 80th entry would have the value 82 in it, to use your example. For a much larger, sparse range, probably the way to go is a binary search.
With a query language you could query for values some distance either side of your input number and then sort through the resulting reduced list. But SQL doesn't have a good concept of "next" or "previous", to give you a "clean" solution.