finding the nearest number in an array - javascript

I have a sorted list of numbers. I want to search the array for a number (lets call it searchVal). So the line of code below works fine if the number is in the array.
var sPos = $.inArray(searchVal, MyArray);
However if it is not in MyArray I want to select the next biggest number, i.e
I'm searching for 8 in the list below I would like it to return 10.
4, 5, 6, 10, 11
I am new to javascript and wondering what the best way to achieve this is? I have seen a filter could be used where any number >= to 8 is returned and then take the min number from this filtered list. Or is this a case when I should make use of the reduce function?

You can use Array.find() on sorted array.
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
console.log([13, 4, 6, 5, 10, 11].sort((a, b) => a > b).find(x => x > 8));

Since the array is sorted you can use
var num = MyArray.find(x => x > 8)

For unsorted data, you could take the absolute delta of an item and check with the delta of last item and return the one with smaller delta.
var array = [5, 4, 11, 6, 10],
find = 8,
nearest = array.reduce((a, b) => Math.abs(a - find) < Math.abs(b - find) ? a : b);
console.log(nearest);

Hi you use the map function to determine the distance to 8.
var array = [4, 5, 6, 10, 11];
var distanceArray = array.map(function(element){
var distance = 8-element
if(distance < 0){
distance = distance * -1;
}
return distance;
})
then you got [4,3,2,2,3]. use Math.min
var minimum = Math.min(...distanceArray);
Now you got 2 as minimum. now found the position
var position = distanceArray.indexOf(minimum);
now you can see whats number is nearest,
var nearest = array[position];
got you 6....

Related

Index Values SumUp to Total

I am trying to improve in my Problem Solving Skills and would love to get some explanation on what it is that I am doing wrong or if I can get a hand in the right direction. My code below is what I am stuck on.
My problem, I am trying to check within the array if it contains any numbers that will sum up to a total given value. Pretty simple but a bit complex for a beginner.
My first Step is to setup a function with two parameters that accept the array and total amount we want.
const array = [10, 15, 7, 3];
function sumUpTotal(array, total) {
}
Then I want to iterate through my array to check each value within the array by using the forEach method to output each value
const array = [10, 15, 7, 3];
function sumUpTotal(array, total) {
array.forEach(value => value)
}
Now that I have all the outputs, I am stuck on how I can check if the numbers add up with each other to give out the total we want. Can someone please help.
The Output should be two numbers that add up to the total.
For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17.
Using forEach() to iterate over each value in the array and includes() to check if any values further ahead in the array sum to your total you can generate an array of unique sum pairs. By only looking forward from the given iteration one avoids generating duplicate pairings. (eg. avoids [[10, 7], [7, 10]] for you example input)
forEach() provides both the value and the index of the current iteration, which makes it simple to use the optional, second fromIndex argument of includes() to only look ahead in the array by passing index+1. If a match is found an array of [value, difference] is pushed to the result array. The return value is an array of sum pairs, or an empty array if there are no matches.
const array = [10, -2, 15, 7, 3, 2, 19];
function sumUpTotal(array, total) {
let result = []
array.forEach((value, index) => {
let diff = total - value;
if (array.includes(diff, index + 1)) result.push([value, diff]);
});
return result;
}
console.log(JSON.stringify(sumUpTotal(array, 17)));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do this using a Set as follows:
function sumUpTotal(array, total) {
// initialize set
const set = new Set();
// iterate over array
for(let i = 0; i < array.length; i++){
// get element at current index
const num = array[i];
// get the remaining number from total
const remaining = total - num;
// if the remaining is already stored in the set, return numbers
if(set.has(remaining)) return [num, remaining];
// else add number to set
else set.add(num);
}
// return null if no two numbers in array that sum up to total
return null;
}
const array = [10, 15, 7, 3];
const total = 17;
console.log( sumUpTotal(array, total) );

JavaScript: Rearrange an array in order – largest, smallest, 2nd largest, 2nd smallest, 3rd largest, 3rd smallest,

Given an array of integers, where the values should be sorted in the following order:
if we have an array
[1, -1, -3, 9, -2, -5, 4, 8,]
we must rearrange it this way: largest number, smallest number, 2nd largest number, 2nd smallest number, ...
[9, -5, 8, -3, 4, -2, 1, -1 ]
I get the first largest and smallest numbers, but can't figure out how to make it dynamic for all values in the array.
I know that I must take two variables, say firstSmallest and firstLargest and point them to the first and last index of the array respectively, run a loop, which I do already in the code below, and store value into new array by incrementing firstSmallest and decrementing firstLargest, but couldn't implement into code.
let unsortedArr = [1, 5, 8 , 7, 6, -1, -5, 4, 9, 5]
let output = [];
function meanderArray(unsorted){
let sorted = unsorted.sort((a, b) => a-b);
let firstSmallest = sorted[0];
let firstLargest = sorted[unsorted.length-1];
for(let i = 0; i <= sorted.length; i++){
//I should increment firstSmallest and decrement firstLargest numbers and store in output
}
return output;
}
meanderArray(unsortedArr);
console.log(output);
You could take a toggle object which takes the property of either the first item or last from an array and iterate until no more items are available.
function meanderArray([...array]) {
const
result = [],
toggle = { shift: 'pop', pop: 'shift' };
let fn = 'shift';
array.sort((a, b) => a - b);
while (array.length) result.push(array[fn = toggle[fn]]());
return result;
}
console.log(...meanderArray([1, 5, 8, 7, 6, -1, -5, 4, 9, 5]));
You can sort an array by descending, then logic is the following: take first from start and first from end, then second from start-second from end, etc.
let unsortedArr = [1, 5, 8 , 7, 6, -1, -5, 4, 9, 5]
let output = [];
function meanderArray(unsorted){
let sorted = unsorted.sort((a, b) => b-a);
let output = []
for(let i = 0; i < sorted.length/2; i++){
output.push(sorted[i])
if(i !== sorted.length - 1 - i){
output.push(sorted[sorted.length - 1 - i])
}
}
return output;
}
let result = meanderArray(unsortedArr);
console.log(result);
You can sort, then loop and extract the last number with pop() and extract the first number with shift().
let unsortedArr = [1, -1, -3, 9, -2, -5, 4, 8,]
let output = [];
function meanderArray(unsorted){
let sorted = unsorted.sort((a, b) => a - b);
for(let i = 0; i < unsortedArr.length + 2; i++){
output.push(sorted.pop());
output.push(sorted.shift());
}
console.log(output);
return output;
}
meanderArray(unsortedArr);
Fastest Meandering Array method among all solutions mentioned above.
According to the JSBench.me, this solution is the fastest and for your reference i have attached a screenshot below.
I got a different approach, but i found that was very close to one of above answers from elvira.genkel.
In my solution for Meandering Array, First I sorted the given array and then i tried to find the middle of the array. After that i divided sorted array in to two arrays, which are indices from 0 to middle index and other one is from middle index to full length of sorted array.
We need to make sure that first half of array's length is greater than the second array. Other wise when applying for() loop as next step newly created array will contains some undefined values. For avoiding this issue i have incremented first array length by one.
So, always it should be firstArr.length > secondArr.length.
And planned to create new array with values in meandering order. As next step I created for() loop and try to push values from beginning of the first array and from end of the second array. Make sure that dynamically created index of second array will receive only zero or positive index. Other wise you can find undefined values inside newly created Meandering Array.
Hope this solution will be helpful for everyone, who loves to do high performance coding :)
Your comments and suggestions are welcome.
const unsorted = [1, 5, 8, 7, 6, -1, -5, 4, 9, 5];
const sorted = unsorted.sort((a,b)=>a-b).reverse();
const half = Math.round(Math.floor(sorted.length/2)) + 1;
const leftArr = sorted.slice(0, half);
const rightArr = sorted.slice(half, sorted.length);
const newArr = [];
for(let i=0; i<leftArr.length; i++) {
newArr.push(leftArr[i]);
if (rightArr.length-1-i >= 0) {
newArr.push(rightArr[rightArr.length-1-i]);
}
}

How to ignore a negative number in Javascript?

I understand that Math.abs is used to convert negative numbers to absolute in JavaScript, but say I want to filter out negative numbers in an array for example, how do I do that? Is there a function for that?
This should solve your issue [1, 2, -3 , 4, -5].filter(val => val > 0);
If you want to eliminate the values, #Antoni 's approach will do.
However, if you want to retain elements but bound the values (also known as clamping) I usually use Math.max(0, number); to set a lower numerical bound - if number is <0, it returns 0.
You can apply this to an array using map:
var array = [1, -2, 3];
array = array.map(number => Math.max(0, number));
//Sets array == [1, 0, 3]
Similarly for an upper bound you can use Math.min(upperLimit, number); and of course you can apply them both for upper and lower bounds:
var array = [1, -2, 3];
const lowerLimit = 0;
const upperLimit = 2;
array = array.map(number => Math.max(lowerLimit, Math.min(upperLimit, number)));
//Sets array == [1, 0, 2]

Javascript array shuffle with padding

What would be the best way to shuffle an array of numbers with the condition that each number must be +3 or -3 of the next/prev number? So, for example [0,1] wouldn't work, but [0,3] would.
Thanks!
Looking at the screenshot it seems you're wanting to pick a random assortment from the list, with no 2 choices being within 3 of each other.
This code takes an array, and gives you a subset of the array satisfying that condition.
You can specify a maximum number of selections too, although you might not always get that many.
var src = [0,1,2,3,4,5,6,7,8,9,10,11,12];
var getRnd = function(max){
var output = [];
var newSrc = src.slice();
var test, index, i, safe;
while (newSrc.length > 0 && output.length < max){
index = Math.floor(Math.random()*newSrc.length);
test = newSrc.splice(index,1);
//Make sure it's not within 3
safe = true;
for (i=0; i<output.length;i++){
if(Math.abs(test-output[i]) < 3){
//abort!
safe=false;
}
}
if(safe){
output.push(test);
}
}
return output;
};
alert(getRnd(4));
A way (likley not the fastes) would be to:
sort array
pick random element to start new shuffled array with (mark element in sorted array as used or remove)
with binary search find next element that is +3 or -3 for the last one (randomly pick between -3 and +3). Make sure element is not marked as used before (otherwise find another one)
repeat 3 till you can find elements.
you either picked all elements from sorted array or such shuffling is not possible.
I think you get O(N*logN) with this (sorting N*logN and picking N elements with logN for each serch).
Assuming that the values in the array cannot be duplicated.
function one(array, mod){
var modArray = [];
for(var index in array){
var item = array[index];
var itemMod = item%3;
if(itemMod === mod){
modArray.push(item);
}
}
return modArray();
}
function two(modArray){
var sortedArray = // sort highest to lowest
for(var index in sortedArray ){
var item = array[index];
if(index > 0 && item[index-1] === item[index]-3){
}else{return false;}
}
return sortedArray.length;
}
function main(array){
var a1 = one(array, 0);
var a2 = one(array, 1);
var a3 = one(array, 2);
var a1c = two(a1);
var a2c = two(a2);
var a3c = two(a3);
return // if a1c is greatest then a1, if a2c greatest then a2 ... etc
}
I think you must be using the phrase "shuffle" in some non-standard way. If all of the numbers are already within +-3 of each other, then sorting the array will put them in the right order, unless there are duplicates, I guess.
More examples would probably be helpful. For instance, are these examples valid, and the sort of thing you're looking for?
[0, 3, 3] -> [3, 0, 3]
[9, 3, 6, 0, 6] -> [0, 3, 6, 9, 6]
[3, 3, 6, 0, 6] -> [0, 3, 6, 3, 6]
It feels like this is probably a solved problem in graph theory - some kind of network traversal with a maximum/minimum cost function.

Find the number in an array that is closest to a given number

I have an Array of integers in javascript, [5,10,15,20,25,30,35]
when given a number x, how can I find the element in the array that is closest to that number?
If the number is over a value, but less than halfway to the next number, I would choose the smaller value, if it were over halfway to the next number, I would choose the higher number.
For example 7 would return 5, but 8 would return 10. How can I accomplish this? Any help or tips would be appreciated. I have searched and cannot find a solution. I'm sure this is sort of common.
Probably the easiest thing to do is sort based on distance from the reference value x, and then take the first item.
The built-in Array.prototype.sort() can take a comparison function which will be called for pairs of values from the array. Then the key is simply to pass in a comparison function which compares the two values based on their distance from the reference value 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];
See this simple demo.
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];
}
If using a functional approach is applicable then you can map the set to tuples of (value, distance) then reduce that set of tuples to the tuple with the smallest distance. We return the value in that tuple.
To explain the useage of _.map. You map all the values in your array to new values and the function will return the array of new values. In this case an array of tuples.
To explain the useage of _.reduce. You reduce the array to a single value. You pass in an array and a memo. The memo is your "running counter" as you move through the array. In this case we check whether the current tuple is closer then the memo and if so make it the memo. We then return the memo at the end.
The code snippet above relies on underscore.js to remove the nitty gritty of functional style javascript
Your example list is sorted. If this is always the case, then binary search for your number. If you don't find the exact number, make the binary search end off by checking the two numbers around where the number would be and return the closest. Be careful with edge cases where all numbers are greater or are all smaller than the target number
If the list isn't always sorted, then go through the list keeping track of the largest number <= the target number and the smallest number >= the target number. Return the one that's closest to the target.
In either solution, you'll need to decide which side to favour if for example you're searching for 2 in [1, 3].
Create a temporary array of the same size as your original array, and populate it with the differences between your x and the array element.
For example, let the temporary array be temp[], and your original array be a[]:
temp[i]=Math.abs(x-a[i]);
Then, return the index of the minimum value in temp[] to the user.
Assuming the array is sorted, step through each adjacent pair of integers in the array. For each pair (say "5 and 10" or "20 and 25"), test if x is in between them, and if so, return whichever one is closer to x (with a bias towards the lower one).
You would also need a special case for when x is less than the first number (return the first number) or greater than the last number (return the last number).
If the array is not sorted, sort it first.
I created my own function since i could not find any that meets my requeriments.
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;
}
};
Since Array.reduce is a reality for so long (even IE9 supports it), the problem is easily solvable with it. This way, no need to sort the array first (no array mutation at all):
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);
You can go further and solve it with only one line of ES6 (ECMAScript 2015) syntax, by using an arrow function (but with no IE support in this case):
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);
Of course, for flexibility and reusability, it's easy to make it as a function:
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));

Categories