Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
i have a sorted array of numbers [2, 5, 12, 34, 56]
and a random number "17".
I need the index of the next highest number from my array. In this case i want to recieve "3" as it is the index of "34" which is the next highest number in my array.
any ideas?
A function that meets the requirements can be as simple as:
function getNextHighestIndex(arr, value) {
var i = arr.length;
while (arr[--i] > value);
return ++i;
}
getNextHighestIndex([2, 5, 12, 34, 56], 17); // 3
getNextHighestIndex([2, 5, 12, 34, 56], 100); // 5
getNextHighestIndex([2, 5, 12, 34, 56], 0); // 0
If there is no value in the array that is higher than the supplied value, it will return the length of the array. If all values in the array are higher, it will return 0.
Running with vzwick's suggestion, you could do this quite neatly with underscore's filter and indexOf methods:
function getNextHighestIndex(arr, number) {
return _.indexOf(arr, _.filter(arr, function(val) {
return val > number
})[0]);
}
getNextHighestIndex([2, 5, 12, 34, 56], 17);
Or vanilla JavaScript:
function getNextHighestIndex(arr, number) {
for (var i = 0; i < arr.length; i ++) {
if (arr[i] > number) {
return i;
}
}
}
getNextHighestIndex([2, 5, 12, 34, 56], 17);
This code will return the index you are looking for, and will return -1 if there is no number greater in the array.
function findNextHighest(array_input, compare_num){
for (i=0;i<array_input.length;i++){
if (array_input[i] > compare_num){
return i;
}
}
return -1; // Value returned if no highest number found in the array
}
See: http://jsfiddle.net/w42wE/3/ (click run)
var MyArray = [2, 5, 12, 34, 56]
var RandomNumber = 17;
var MinGreaterThanPos;
for (var i =0; i < MyArray.length; i++) {
if (MyArray[i] <= RandomNumber)
continue;
if (typeof(MinGreaterThanPos) == 'undefined' || MyArray[i] < MinGreaterThanPos)
{
MinGreaterThanPos = i;
}
}
alert(MinGreaterThanPos);
for (var i=0; i<ary.length; i++;) {
if (ary[i] > target)
return i;
}
var myArray = [2, 5, 12, 34, 56],
randomNumber = 17;
var result = $(myArray)
.map(function(i){ return (this > randomNumber) ? i : null })
.get() // un-wraps the jQuery object to a proper Array
.shift();
That being said, OP might want to look into underscore.js as a leaner alternative - honestly, jQuery is a bit of an overkill for the task.
If you want something a bit more sophisticated, implement a divide&conquer search algorythm:
function find_next(list, query) {
var pointer_upper = list.length - 1;
var pointer_lower = 0;
var pointer_tmp;
while (pointer_upper - pointer_lower > 1) {
pointer_tmp = Math.ceil((pointer_upper + pointer_lower)/2)
if (list[pointer_tmp] <= query) {
pointer_lower = pointer_tmp;
} else {
pointer_upper = pointer_tmp;
}
}
return pointer_lower + 1;
}
find_next([2, 5, 12, 34, 56], 17); // returns 3
Note: it is possible that this function will return a result that is less then the query (if all the elements in list are less then query). So maybe you would like to check for that before returning.
Related
I am trying to write a simple "getRandomIndex" function to return a random and unused index number for a given array but I get "Maximum call stack size exceeded" error at let rndIdx = Math.floor(Math.random() * (arr.length - 0)) + 0;.
const arr = [81, 33, 45, 22, 97, 19, 60];
const usedIndexes = []; // I am trying to store used indexes here
function getRandomIndex() {
let rndIdx = Math.floor(Math.random() * (arr.length - 0)) + 0;
if(usedIndexes.includes(rndIdx)) {
getRandomIndex();
return;
} else {
usedIndexes.push(rndIdx);
}
return rndIdx;
}
// if the array length is more than 10, I always get "call stack size exceed" error.
for(let i = 0; i < arr.length; i++) {
// I need to use all elements in the array eventually
console.log(getRandomIndex());
}
What I am missing?
You must check that the length of the array allows for different unused numbers.
if (usedIndexes.length>=arr.length) {
return null
}
You need to return the output of getRandomIndex() rather than calling it, dumping the output, then returning nothing (which gives you undefined)
Fixed Code
const arr = [81, 33, 45, 22, 97, 19, 60];
const usedIndexes = []; // I am trying to store used indexes here
function getRandomIndex() {
let rndIdx = Math.floor(Math.random() * (arr.length - 0)) + 0;
if(usedIndexes.includes(rndIdx)) {
// used to be
// - getRandomIndex();
// - return;
return getRandomIndex();
} else {
usedIndexes.push(rndIdx);
}
return rndIdx;
}
// if the array length is more than 10, I always get "call stack size exceed" error.
for(let i = 0; i < arr.length; i++) {
// I need to use all elements in the array eventually
console.log(getRandomIndex());
}
Output
0
2
4
3
1
6
5
I was given this problem at one of my interviews and was told I have 20 minutes to solve it. This is the answer I came up with ( 2 versions ). Can you let me know which version you prefer and why, and if you have a better idea of how to solve it (less complex, less memory usage, etc.) Please share.
Problem: You have an array of random numbers that range from 0 to 100 elements.
Write a function that will split this array into several arrays, each containing elements in the following range: (0-10],(10-20],(20-30], etc up to a 100].
Write a function that outputs these arrays in a form of a simple graph, where each delimiter represents a single value in the array.
Array = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55,
65, 42, 99, 4];
Desired outcome:
5 Elements in array: ***** - 1,5,6,3,4
3 Elements in array: *** - 10,12,11
2 Elements in array: ** - 22,21
No Elements in array.
2 Elements in array: ** - 45,42
3 Elements in array: *** - 52,51,55
2 Elements in array: ** - 64,65
1 Elements in array: * - 71
No Elements in array.
2 Elements in array: ** - 95,99
// Version 1
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const splitArray = (inputArray, range) => {
const newArray = [];
do {
let tempArray = [];
tempArray = inputArray.filter((item) => {
if (item >= range && item < range + 10) return item;
});
range += 10;
newArray.push(tempArray);
} while (range + 10 <= 100);
return newArray;
};
const printArrays = (array, delimiter) => {
let toPrint = "";
for (index in array) {
let stars = array[index].length;
let string = "";
for (let i = stars; i > 0; i--) {
string += delimiter;
}
toPrint += stars
? `${stars} Elements in array: ${string} - ${array[index]} \n`
: "No Elements in array. \n";
}
return toPrint;
};
console.log(printArrays(splitArray(arr, 0), "*"));
// Version 2
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const getArrays = (inputArray) => {
const newArray = [];
let min = 0;
let max = 10;
do {
const tempArray = [];
for (i in arr) {
let val = arr[i];
val >= min && val < max ? tempArray.push(val) : "";
}
min += 10;
max += 10;
newArray.push(tempArray);
} while (max <= 100);
return newArray;
};
const printArrays = (array, delimiter) => {
for (index in array) {
let stars = array[index].length;
let string = "";
for (let i = stars; i > 0; i--) {
string += delimiter;
}
console.log(
stars ? `${stars} Elements in array: ${string} - ${array[index]}` : "No Elements in array."
);
}
};
printArrays(getArrays(arr), "^");
Both approaches have moderate issues.
The first approach does
let tempArray = [];
tempArray = inputArray.filter((item) => {
if (item >= range && item < range + 10) return item;
});
Better to just declare the tempArray as the filtered array to begin with.
const tempArray = inputArray.filter(...
Also, return item is suspicious inside a filter - all the filter callback cares about is whether its return value is truthy or falsey. Returning the array item when you actually want to indicate that the value should be included in the output is a common mistake. It happens not to be a problem here because 0 isn't a possibility, but it's still confusing. A better choice would be to do
const tempArray = inputArray.filter(
item => item >= range && item < range + 10
);
(and maybe rename range to startOfRange)
Both of your approaches are also iterating through the entire input array multiple times (once for each range), which seems a bit wasteful - better to iterate through the input once.
Your second approach uses for (i in arr), and both approaches are doing for (index in array). This is a bad idea, and since you don't actually care about the index you're iterating over, it'd make sense to use for..of loops instead.
I think a better looking approach that iterates through the input just once would be:
const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const getArrays = (inputArray) => {
const grouped = {};
for (let i = 0; i < 100; i += 10) {
grouped[i] = [];
}
for (const item of inputArray) {
const rangeProp = Math.floor(item / 10) * 10;
grouped[rangeProp].push(item);
}
return Object.values(grouped);
};
const printArrays = (groupedArrays, delimiter) => {
for (const array of groupedArrays) {
const stars = delimiter.repeat(array.length);
console.log(
stars
? `${array.length} Elements in array: ${stars} - ${array.join(',')}`
: "No Elements in array."
);
}
};
printArrays(getArrays(arr), "*");
I will do that this way :
This approach is simple: it retrieves the values one by one and adds them to the array corresponding to their range.
const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
let ranges = arr.reduce((a,x)=>
{
let range = (x/10)|0 // get range start value 0 to 9
a[range] ??= [] // create the array of if it does not already exist
a[range].push(x)
return a
},{})
console.log('ranges=', ranges ) // so that noobs can visualize this result
for (let r = 0; r < 10; r++ )
{
if (!ranges[r])
document.write('No Elements in array.<br>')
else
{
let count = ranges[r].length
document.write(`${count} Elements in array: ${'*'.repeat(count)} - ${ranges[r].join(',')}<br>`)
}
}
.as-console-wrapper {max-height: 100% !important; width:20%; top: 0;
margin-left: 80%; }
.as-console-row::after {display: none !important;}
range = (x/10)|0 // get range start value 0 to 9
example in case of x = 25 -> 25/10 give 2.5 and 2.5 | 0 give 2 -> integer part value of 2.5
| is the OR boolean operator, work only on integers values so it return an interger
??= is Logical nullish assignment
I want to write a function that takes array as an argument and returns how many numbers can be divided by 12. However, if array has a number higher than 111 then it should return 0;
I wrote this:
function isDivisble(array) {
let numberOfNum = 0;
for(let i=0; i < array.length; i++) {
if(array[i] % 12 == 0 && array[i] < 111) {
numberOfNum = numberOfNum + 1 ;
} else {
numberofNum = 0;
}
}
return console.log(numberOfNum);
}
let test = [12, 24, 36, 44, 55, 255];
isDivisble(test)
I realized that this code checks individually whether the current number is divisible and not higher than 111 and not globally whether the array has a number higher than 111, but I dont understand how to make a general array check.
Is writing for loop with if statement to check and then another for loop inside if statement makes it a little bit spaghetti?
You can use some to check if there is any element which is greater than 111 first.
Then you can use filter to get element that is divisible by 12.
Like this:
const isDivisible = (arr) => {
if (arr.some((e) => e > 111)) return 0;
return arr.filter((e) => e % 12 === 0).length;
};
const test = [12, 24, 36, 44, 55, 48];
console.log(isDivisible(test));
I've slightly modified your function that returns 0 if a number is greater than 111 else it checks if it is divisible by 12
function isDivisble(array) {
let count = 0;
for(let i=0; i<array.length; i++){
if(array[i] > 111){
return 0;
}else{
if(array[i] % 12 === 0){
count++
}
}
}
return count;
}
let test = [12, 24, 36, 44, 55, 255];
console.log(isDivisble(test));
The some array method will do the trick:
array.some(value => { return value > 111 }) will return true if any of its values is greater than 111.
You can also check if every array value respects a certain condition by using array.every with a similar callback:
array.every(value => { return value <= 111 }) is true only if every value in the array is lower than or equal to 111.
The best generic solution is the oene below
Logic
Filter the array for number greater that 111. If this filter returns an array with a length greater than 1 then return 0
Else filter the array for numbers divisible by 12. No need to check number is less than 111. Because if that number is greater than 111 the function might have already returned 0.
Retun the length of the above filter.
Working Fiddle
function isDivisbleGeneric(arr) {
const numberGreaterThanLimit = arr.filter((node) => node > 111);
let returnCount;
if(numberGreaterThanLimit.length > 0) {
returnCount = 0;
} else {
const divisibleBy12 = arr.filter((node) => node %12 === 0);
returnCount = divisibleBy12.length;
}
return returnCount;
}
let test = [12, 24, 36, 44, 55, 255];
const count = isDivisbleGeneric(test);
console.log(count);
One Line Solution
const isDivisbleOneLine = (arr) => arr.filter((node) => node > 111).length > 0 ? 0 : arr.filter((node) => node %12 === 0).length;
let test = [12, 24, 36, 44, 55, 255];
const count = isDivisbleOneLine(test);
console.log(count);
function isDivisble(array) {
// at the beginning, do from here
if (array.some(p=>p > 111)) {
return 0;
}
// Rest xxxxxx
}
Where is the mistake? I want to sum every number in the array. The alert says NaN.
var numbers = [10, 42, 5, 87, 61, 34, 99];
var i = 0;
var e = 0;
while(i <= numbers.length) {
e = e + numbers[i];
i++;
}
alert(e);
This line is the reason:
while(i <= numbers.length) {
Arrays are 0 index so you can go from index 0 (inclusive) until numbers.length (exclusive). You are going beyond that limit, causing you to access an element that isn't defined at the given index. You must do this instead:
while(i < numbers.length) {
Alternatively using the ES2015 syntax you can do it like this.
let numbers = [10, 42, 5, 87, 61, 34, 99];
let sum = numbers.reduce((a,b) => a + b);
You can read about Array.prototype.reduce(accumulator, element, callback, startingValue) here.
Your condition is wrong, just use < insteead of <=
while(i < numbers.length)
There's a few ways you can improve this. The first is that you want to change your condition to i < numbers.length, not i <= numbers.length. As you've written it, the last number will never be counted.
Another way you can improve this is using the += notation -- there's no need to write e = e + numbers[i] when you can write e += numbers[i].
You could íterate from the end of the array with a post increment and a check for truthyness in the while condition.
Inside just add the item.
var numbers = [10, 42, 5, 87, 61, 34, 99],
i = numbers.length,
e = 0;
while (i--) {
e += numbers[i];
}
console.log(e);
The problem is in array length You are checking because array index starts with 0. In that way when doing:
i <= numbers.length
You are checking [0: 10, 1: 42, 2: 5, 3: 87, 4: 61, 5: 34, 6: 99, 7:???] because numbers length is 7. To solve it just do:
i < numbers.length
where You don't check non existing number in array.
Here is how we were thought in school:
//main code//
var numbers = [10, 42, 5, 87, 61, 34, 99];
var result = sumIntArray(numbers);
//end of main code//
function sumIntArray(array){
var result = 0;
for (var i = 0; i < array.length; i++) {
if (array[i].isInteger()) {
result += array[i];
} else {
if (i === 0) {
alert("1st object in array is not number, will skip...");
}
else if (i === 1) {
alert("2nd object in array is not number, will skip...");
}
else if (i === 2){
alert("3rd object in array is not number, will skip...");
}
else {
alert((i+1).toString() + "th object in array is not number, will skip...");
}
}
}
return result;
}
The for loop adds this i++ You make in a while loop and makes code a bit more clear.
No need for declaring i in main code :)
Always make functions to simplify main code.
Make function that will never make mistake even if somebody wants to break The logic.
Although don't make school break Your creativity, Your code is great! :)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How might I find the largest number contained in a JavaScript array?
I am having trouble getting this code to work. I have been at it for a while trying to figure it out. When I look at the console it just displays 0. What did I do wrong?
Here is my code:
var array = [3 , 6, 2, 56, 32, 5, 89, 32];
var largest= 0;
for (i=0; i<=largest;i++){
if (array>largest) {
var largest=array[i];
}
}
console.log(largest);
var arr = [3, 6, 2, 56, 32, 5, 89, 32];
var largest = arr[0];
for (var i = 0; i < arr.length; i++) {
if (largest < arr[i] ) {
largest = arr[i];
}
}
console.log(largest);
You need to define i or else it become a global variable.
Don't redefine largest in the loop.
Since you're looping through the array, use i < array.length instead of i <= largest.
Since you're comparing each of the items in the array to largest, use if(largest < array[i]) instead of if(array > largest)
You should set largest equal to the first element in the array because what if all the numbers are negative?
array is a bad variable name because it's too similar to Array (the array constructor). Try arr instead.
One liner:
var largest = Math.max.apply(0, array);
More info here: Javascript max() function for 3 numbers
The code below is fixed and should work. The problem was that in this line if (array>largest) { You were not providing the index of the array. By changing the code to this if (array[i]>largest) { it works. Notice that I added the [i] to the end of array in the if statement.
var array = [3 , 6, 2, 56, 32, 5, 89, 32];
var largest= 0;
for (i=0; i<array.length; i++){
if (array[i]>largest) {
largest=array[i];
}
}
console.log(largest);
Just one line :)
var array = [3 , 6, 2, 56, 32, 5, 89, 32],
largest = array.sort((a,b)=>a-b).reverse()[0];
or even better
...
largest = array.sort((a,b)=>a-b)[array.length - 1];
UPD, all code above is sucks when you add for example 9 in array my guess because by default numbers treated as strings in sort, there is better version
var array = [3 , 6, 2, 56, 32, 5, 89, 32, 9], largest;
array.sort(function(a, b) {
largest = a > b ? a: b;
});
although in performance wise forEach loop suggested in comments are better
http://jsperf.com/array-sorting-javascript-stack
UPD2, okay, code above has some bad parts in it, so will not work as expected. Another try:
array.sort(function(a, b) {
return a - b;
});
largest = array[array.length - 1];
You have a few small mistakes. First:
if (array>largest) {
It should instead be:
if ( array[i]>largest) {
Second:
for ( i = 0; i <= largest; i++) {
should be
for (i = 0; i <= array.length; i++) {
var array = [3 , 6, 2, 56, 32, 5, 89, 32];
var largest= array[0];
for (i=0; i<=largest;i++){
if (array[i]>largest) {
largest=array[i];
}
}
You have two issues in your code. First, array>largest should be array[i]>largest. Second, you are declaring a new largest variable inside the if which isn't the same as the one outside. Remove var from the assignment of the new largest value.