I have array with decimal nos such as
var idArray = ["98.40", "111.46", "144.47", "180.48", "217.49", "284.50", "424.51", "571.52", "1887.53", "1960.54", "1972.55", "2118.56", "2167.57", "2467.58", "2480.59", "2488.60", "2662.61", "2671.62", "2767.63", "2982.64", "3168.65", "3263.66", "3295.67", "3369.68", "3579.69", "3592.70", "3600.71", "3605.72", "3620.73", "3646.74", "3852.75", "3857.76", "4031.77", "4489.78", "4975.79"]
I found the minimum value in the array as below
var result = Math.min.apply(null, idArray );
I got result as 98.4
Is there a way to return actual value in the array as 98.40
You could code your own:
minInArr = function(arr) {
var smallest = arr[0];
for(var i=1; i<arr.length; i++){
if(parseInt(arr[i],10) < smallest){
smallest = arr[i];
}
}
return smallest
}
Made this code based on this one:
Return index of greatest value in an array
There are a couple of methods in addition to those already here (though one is pretty similar to adeneo's). One is to copy the array, sort it, then get the 0 index value:
var min = idArray.slice().sort(function(a,b){return a - b})[0];
If you don't care about sorting the original array, drop the .slice() part.
Another way is to use Math.min to get the value, then use some to find it in the original array. The benefit of some is that it will stop at the first match:
var min, temp = Math.min.apply(Math, idArray);
idArray.some(function(v){ return temp == v? min = v : false});
console.log(min);
There are pros and cons to each, choose whatever is easiest to maintain.
If it really is an array, you can do it the old fashion way with iteration instead, and return the actual string instead of the parsed number, that way number of decimals is not important.
var idArray = ["98.40", "111.46", "144.47", "180.48", "217.49", "284.50", "424.51", "571.52", "1887.53", "1960.54", "1972.55", "2118.56", "2167.57", "2467.58", "2480.59", "2488.60", "2662.61", "2671.62", "2767.63", "2982.64", "3168.65", "3263.66", "3295.67", "3369.68", "3579.69", "3592.70", "3600.71", "3605.72", "3620.73", "3646.74", "3852.75", "3857.76", "4031.77", "4489.78", "4975.79"];
var result = idArray[0];
idArray.forEach(function(x) {
if (parseFloat(x) < result) result = x; // find smallest number as string instead
});
document.body.innerHTML = result;
or, you could just sort the array and get the first item (I sliced it to not modify the original)
var result = idArray.slice().sort(function(a,b) {
return a - b;
}).shift();
or, use Array.reduce
var result = idArray.reduce(function (a,b) {
return parseFloat(a) < parseFloat(b) ? a : b;
});
Try:
var roundedResult = parseFloat(result).toFixed(2);
The trailing zero has no importance and hence it is truncated. So you have no other go other than storing it as a string.
var result = Math.min.apply(null, idArray);
result = (result+"").test(/\.\d\d$/) ? result : result + "0"
Applying Math.min will always coerce your answer to a number, if you coerce it back to a string you loose any trailing zeros. As others have suggested if you know you will always have a fixed number of digits after the decimal you could use .toFixed.
A better solution that doesn't rely on having a fixed number of decimal points would be to use .reduce:
var result,
idArray = ["98.40", "111.46", "144.47", "180.48", "217.49", "284.50", "424.51", "571.52", "1887.53", "1960.54", "1972.55", "2118.56", "2167.57", "2467.58", "2480.59", "2488.60", "2662.61", "2671.62", "2767.63", "2982.64", "3168.65", "3263.66", "3295.67", "3369.68", "3579.69", "3592.70", "3600.71", "3605.72", "3620.73", "3646.74", "3852.75", "3857.76", "4031.77", "4489.78", "4975.79"];
result = idArray.reduce(function (prev, cur) {
if (+prev < +cur) {
return prev;
} else {
return cur;
}
});
console.log(result); // "98.40"
A quick explanation of what this does:
.reduce iterates over the array and calls the provided function once for each item in the array.
This code just uses the first two parameters available in the function, but there are a couple of others available too. The first parameter is the value returned from the previous call (prev, which will be undefined on the first call). The second parameter will be the value of the current item in the array (cur).
Before comparing the the two they are each coerced from strings to numbers using the Unary plus operator.
If prev is smaller it is returned and the next time the function runs prev will be the same, otherwise cur is returned and become the new value of prev on the next call. It is important to note that when the variables were coerced to compare them that just changed the values being compared in the conditional statement, it did not change the actual value stored in the variable, it remains a string.
After the function has been called on the last item in the array the final value of prev is returned and stored in result.
You could shorten it a little using a ternary statement:
result = idArray.reduce(function (prev, cur) {
return +prev < +cur ? prev : cur;
});
If you aren't afraid to use ES6 syntax (not all browsers currently support it) you could make it even shorter with a arrow function:
result = idArray.reduce((prev, cur) => +prev < +cur ? prev : cur);
The one potential (but unlikely) problem with this approach is that it coerces prev every time it makes a comparison. This adds a tiny bit of overhead to each step in the loop. If performance is a concern it would be better to get away from trying to do it with a one-liner and write a function to do it:
var arrayMin = function (arr) {
var i,
len,
prev, // prev and cur will hold numbers that are coerced from strings
cur, // once when they are first encountered
minIndex; // keep track of the index of the smallest item rather
// than copying a string every time we find a smaller number
prev = +arr[0];
minIndex = 0;
for (i = 1, len = arr.length; i < len; i += 1) {
cur = +arr[i];
if (cur < prev) {
prev = cur;
minIndex = i;
}
}
return arr[minIndex];
};
var result = arrayMin(idArray);
Related
I'm new to coding, still learning. My friend gave me a task to write a function that does return the 2nd highest number from an array, I've managed to do it using array.prototype.sort(). He said to replace "-" with a "<" or ">" to make the code more clear, that's where the problem started.
I'm using VCS on windows, and it's not working properly.
My friend uses a mac, everything works fine.
Tried it on jsfiddle, everything works fine.
const secondMax = (arr) => {
return arr.sort((a, b) => b - a)[1]; //does return the correct number after console.log()
};
const secondMax = (arr) => {
return arr.sort((a, b) => a < b)[1]; //does not
};
"a < b" should be sorting descending
"a > b" should be sorting ascending
But no matter which operator I use, the sorting fails and just returns the second number from the array
You're supposed to return a number, not a boolean. So the first is correct. The latter might work by chance on some javascript engines, but it's not guaranteed to.
sort sorts the array as String by default. If you pass a comparator, then it's a function which will depend on two parameters and return:
negative, if the first parameter is smaller than the second
0 if they are equal
positive, if the first parameter is greater than the second
Using a logical operator instead of the above is mistaken.
However, if you are interested in finding the second largest number, then it's better to do it using a cycle:
var largestNumbers = [];
var firstIndex = (arr[0] < arr[1]) ? 1 : 0;
largestNumbers.push(arr[firstIndex]);
largestNumbers.push(arr[1 - firstIndex]);
for (var i = 2; i < arr.length; i++) {
if (largestNumbers[1] < arr[i]) {
if (largestNumbers[0] < arr[i]) {
largestNumbers[1] = largestNumbers[0];
largestNumbers[0] = arr[i];
}
}
}
This is quicker than sorting an array and more importantly, it does not destroy your initial order just to find the second largest number.
Hello everyone !
I'm currently working to get a user input and parse it my way. The input represents integer ranges or single integers.
Let's say I get the following ranges array :
const ranges = [`1-6`, `8`, `12-20-18`, `22-21`, `46-42-44`];
Now I need a complete integer list so I wrote this chunk :
const list = ranges.reduce ((array, range) => {
console.log (array);
if (!range.incldues (`-`)) return array.push (parseInt (range)); // Single integer
const milestones = range.split (`-`).map (milestone => parseInt (milestone)),
min = Math.min (...milestones),
max = Math.max (...milestones);
for (let i = min; i <= max; i++) array.push (i);
console.log (array);
return array;
}, []);
The thing is I quicly got a "Uncaught TypeError: array.push is not a function" and console.logging my variables showed that after the first reduce iteration, array took the value (int) 7, despite being an array just before the return statement.
Here is an illustration of it
Could someone point out where it went wrong ? How to prevent it doing so ? And furthermore, if someone could explain WHY it went wrong, it would be perfect.
Thanks !
Two issues:
The method name is .includes (not incldues)
Array.prototype.push returns the new length of the array, not the array itself. Use push first, then use return array on the next line.
Fix those, and it works as expected:
const ranges = [`1-6`, `8`, `12-20-18`, `22-21`, `46-42-44`];
const list = ranges.reduce((array, range) => {
if (!range.includes(`-`)) {
array.push(parseInt(range)); // Single integer
return array;
}
const milestones = range.split(`-`).map(Number),
min = Math.min(...milestones),
max = Math.max(...milestones);
for (let i = min; i <= max; i++) array.push(i);
return array;
}, []);
console.log(list);
Note that because the Number function converts a non-number to a number, you can simply pass it to .map rather than using .map (milestone => parseInt (milestone)) (which is a bit wordy).
I'm doing the Free Code Camp series of tutorials and I got the answer right but don't understand a few things ...
Exercise:
Use the reduce method to sum all the values in array and assign it to singleVal.
singleVal should be equal to the sum of all items in the array variable.
You should have made use of the reduce method.
var array = [4,5,6,7,8];
var singleVal = 0;
singleVal = array.reduce(function(previousVal,currentVal){
return previousVal + currentVal;
},0);
I got the answer right by following the example basically.. but I can't understand why there is a comma zero at the end - like what is the point of it?
The comma zero at the end denotes the initial value.
The syntax of reduce is array.reduce(function(total, currentValue, currentIndex, arr), initialValue). Mentioning initialValue is Optional. A value to be passed to the function as the initial value.
Consider the following example:
var array = [4,5,6,7,8];
var singleVal = 0;
//reduce function takes 5 as the initial value then sums up the values of
//the array.
singleVal = array.reduce(function(previousVal,currentVal){
return previousVal + currentVal;
},5); //5 is passed to the function as the initial value.
console.log(singleVal) //35
I am working on this problem from coderbytes:
Using the JavaScript language, have the function SecondGreatLow(arr) take the array of numbers stored in arr and return the second lowest and second greatest numbers, respectively, separated by a space. For example: if arr contains [7, 7, 12, 98, 106] the output should be 12 98. The array will not be empty and will contain at least 2 numbers. It can get tricky if there's just two numbers!
My solution works by removing the greatest and lowest values from the array and then using Math methods to return the second highest and lowest values.
However, when there are two or more instances of the greatest or lowest elements of the array, and their index positions are adjacent to each other, I believe only the first instance of this value is removed and the flow skips over the second instance.
Is there any way to have the loop run through the same index value twice in order to process adjacent greatest or lowest values?
Here are the two iterations of my solution which I've tested.. my original attempt using .forEach and my second using a for loop.. I've console.logged a situation in which the code works and in which it doesn't for each attempt.
I'm really new to all this, almost a month of learning in my free time so explaining yourself as if I'm really dumb is appreciated. Thanks!!!
// * First attempt - using .forEach method *
// outputs the second lowest value in the array
function secondLowest (arr) {
var g = function () {
return Math.min.apply(null, arr);
}
arr.forEach(function (val, indx, arr) {
if (val === g()) {
arr.splice(indx, 1);
}
});
lowestVal = g(); // store this value to be added back in for the secondGreatest function (in case there were only two digits in the arr argument)
return Math.min.apply(null, arr);
}
// number trimmed from the array in the function secondLowest..
// to be added back in for the function secondGreatest
var lowestVal = 0
// adds back the lowest value which was trimmed..
// outputs the second greatest value
function secondGreatest (arr){
arr.splice(0,0,lowestVal);
var g = function () {
return Math.max.apply(null, arr);
}
arr.forEach(function (val, indx, arr) {
if (val === g()) {
arr.splice(indx, 1);
}
});
return Math.max.apply(null, arr);
}
// putting together the output
function SecondGreatLow (arr) {
return secondLowest(arr) + " " + secondGreatest(arr);
}
console.log(SecondGreatLow([1,2,3,4,5]));
console.log(SecondGreatLow([1,1,2,2,3,3,4,4,5,5]));
// * Second attempt - using for loops *
// outputs the second lowest value in the array
function secondLowest (arr) {
var g = function () {
return Math.min.apply(null, arr);
}
lowestVal = g();
for (var i = 0; i < arr.length; i++) {
if (arr[i] === g()) {
arr.splice(i, 1);
}
}
return Math.min.apply(null, arr);
}
// number trimmed from the array in the function secondLowest..
// to be added back in for the function secondGreatest
var lowestVal = 0
// adds back the lowest value which was trimmed..
// outputs the second greatest value
function secondGreatest (arr){
arr.splice(0,0,lowestVal);
var g = function () {
return Math.max.apply(null, arr);
}
for (var i = 0; i < arr.length; i++) {
if (arr[i] === g()) {
arr.splice(i, 1);
}
}
return Math.max.apply(null, arr);
}
// putting together the output
function SecondGreatLow (arr) {
return secondLowest(arr) + " " + secondGreatest(arr);
}
console.log(SecondGreatLow([1,2,3,4,5]));
console.log(SecondGreatLow([1,1,2,2,3,3,4,4,5,5]));
I tried using the delete operator in order to keep the argument array length consistent (rather than shortening it with splice which I think allows the adjacent value to pass into the removed element's index position and not be processed in the next runthrough of the for loop or forEach method) but the Math.min/max.apply methods don't like having 'undefined' in the array argument.
Also if my code is looking ugly/annoying and makes you cringe then please take this opportunity to vent.. helps me learn to write code that doesn't piss people off ;)
** Solution Found **
Thank you for reminding me of the sort method!(function?) Here's what I ended up with:
function SecondGreatLow (arr) {
var secondLow = 0,
secondHigh = 0;
arr.sort(function(a,b){
return a-b;
});
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== arr[i-1]) {
secondLow = arr[i];
break;
}
}
for (var j = (arr.length-2); j >= 0; j--) {
if (arr[j] !== arr[j+1]) {
secondHigh = arr[j];
break;
}
}
return secondLow + " " + secondHigh;
}
console.log(SecondGreatLow([1,1,2,2,3,3,4,4,5,5]));
What an awesome community.. I'll be back with more questions and hopefully I'll feel confident enough to even answer some questions in the near future. Thanks!
I feel like perhaps I'm missing something, but the challenge doesn't seem to include a requirement for removing items from the original array, so I don't see why you're modifying it in such a way. The requirements you provided simply state to return 'a b' where a is the second lowest, and b the second highest.
So, I would first recommend sorting the list. Since you know you're working at the upper and lower bounds, you don't have to iterate over anything (nor should you). Your test arrays are already sorted, but ensuring order will make your code more robust and able to handle other inputs. Check out the Arrays API for more details.
While it seems it may be beyond the scope of your problem, you may also want to look into sorting algorithms to learn more about how that all works, rather than relying solely on the API.
Once sorted, you should be able to easily compare inwards from the boundaries to get your second lowest and second highest values.
Also, you shouldn't need to utilize the Math API, simple inequality operators should do the trick (< and >).
EDIT: While I recommend working on the problem yourself, here is a simple solution to the problem. I place it here so if you get stuck you can reference this (and the associated comments) for guidance.
function SecondGreatLow(arr) {
var i;
var j;
var lowest;
var highest;
var secondLowest;
var secondHighest;
//Sort Array
arr.sort(function (a, b) {
return a - b;
});
//Get Bounds
//Since we sorted the array, and the default sort is in
//ascending lexicographical order, then we're guaranteed that
//our 'lowest' value is at index 0 and our 'highest' value is
//at index arr.length -1. Note that these values may be
//equal.
lowest = arr[0];
highest = arr[arr.length - 1];
//Search for second lowest.
for (i = 0; i < arr.length; i++) {
if (arr[i] > lowest) {
secondLowest = arr[i];
break;
}
}
//If we reach the end of the array, but didn't
//find a greater value, then, since the array is sorted,
//we're guaranteed that all values in the array are equal.
//Therefore, the required value comparisons have no meaning,
//and we return 'undefined'.
if (secondLowest === 'undefined') {
return 'undefined';
}
//Search for second highest, working backwards from the
//high end of the array until we reach our crossover point
//with the previous search. Either some value > arr[i] is the
//second highest, or arr[i] is, so there's no point in looking
//at values in the indices lower than i.
for (j = arr.length - 1; j >= i; j--) {
if (arr[j] < highest) {
secondHighest = arr[j];
break;
}
}
return secondLowest + ' ' + secondHighest;
}
var result = SecondGreatLow([3,3,4,5,4,6]);
console.log(result);
JSFiddle
You may create a priority queue limited by 2 elements, then feed it with all the array and pop the value, which would be the answer.
The trivial implementation would look like:
function UniqueNElementSortedQueue(length, comparison) {
this.length = length;
this.data = [];
this.comparison = comparison;
}
UniqueNElementSortedQueue.prototype.push = function(v) {
if (this.data.indexOf(v) > -1) {
return;
}
this.data.push(v);
this.data.sort(this.comparison);
this.data.length = this.length;
};
UniqueNElementSortedQueue.prototype.popIfN = function() {
if (this.data.length == this.length) {
return this.data[this.length - 1];
}
};
JSFiddle: http://jsfiddle.net/fmfv67xy/
The solution is O(N) (one might argue that I have sorting internally and they would be right :-)) by number of operations and O(N) by additional memory (where N is linear to the "next-lowest/greatest" index value)
As the description does not define what to return if it was not sufficient data fed - my implementation returns undefined.
Actually, let me turn my comment into an answer, since I think it always helps to also worry about performance:
Create 4 local variables:
largest and second_largest initialized to a number smaller than anything you'd expect in your array, or to the smallest possible value that your data-type can take on (-2^31 - 1)
smallest and second_smallest initialized to a number larger than anything you'd expect in your array, or the largest possible value for your data-type (2^31)
Loop over your array once:
If you find a number larger than largest, set second_largest to largest and largest to that number
If you find something smaller than largest but larger than second_largest, set second_largest to that number
If you find a number smaller than smallest, set second_smallest to smallest and smallest to that number
If you find something larger than smallest but smaller than second_smallest, set second_smallest to that number
When you're done with your loop, your answer is contained in second_largest and second_smallest
Given how small your arrays seem to be, you might not notice much of a performance difference between this answer and the other suggested ones, but I think it's a good habit to get into to always keep this concern in the back of your head for every line of code you write. In this answer, you process every array element exactly once (i.e. the algorithm runs in O(n)), whereas adding a sorting step leads to every element being processed multiple times in a general case (the best sorting algorithms (Timsort, for example) have an expected runtime of O(n log n)).
One thing to note:
#elclanrs mentioned a special case in his comment ([1, 1]), which according to the definition of the problem does not have a defined solution (multiple 1s all would be considered the largest number, so there is no second-largest). In this case, the algorithm above will still have second_largest and second_smallest set to their initial values.
I have an array of objects in javascript. I use jquery.
How do i get the first element in the array? I cant use the array index - as I assign each elements index when I am adding the objects to the array. So the indexes arent 0, 1, 2 etc.
Just need to get the first element of the array?
If you don't use sequentially numbered elements, you'll have to loop through until you hit the first one:
var firstIndex = 0;
while (firstIndex < myarray.length && myarray[firstIndex] === undefined) {
firstIndex++;
}
if (firstIndex < myarray.length) {
var firstElement = myarray[firstIndex];
} else {
// no elements.
}
or some equivalently silly construction. This gets you the first item's index, which you might or might not care about it.
If this is something you need to do often, you should keep a lookaside reference to the current first valid index, so this becomes an O(1) operation instead of O(n) every time. If you're frequently needing to iterate through a truly sparse array, consider another data structure, like keeping an object alongside it that back-maps ordinal results to indexes, or something that fits your data.
The filter method works with sparse arrays.
var first = array.filter(x => true)[0];
Have you considered:
function getFirstIndex(array){
var result;
if(array instanceof Array){
for(var i in array){
result = i;
break;
}
} else {
return null;
}
return result;
}
?
And as a way to get the last element in the array:
function getLastIndex(array){
var result;
if(array instanceof Array){
result = array.push("");
array.pop;
}
} else {
return null;
}
return result;
}
Neither of these uses jquery.
Object.keys(array)[0] returns the index (in String form) of the first element in the sparse array.
var array = [];
array[2] = true;
array[5] = undefined;
var keys = Object.keys(array); // => ["2", "5"]
var first = Number(keys[0]); // => 2
var last = Number(keys[keys.length - 1]); // => 5
I was also facing a similar problem and was surprised that no one has considered the following:
var testArray = [];
testArray [1245]= 31;
testArray[2045] = 45;
for(index in testArray){
console.log(index+','+testArray[index])
}
The above will produce
1245,31
2045,45
If needed you could exist after the first iteration if all that was required but generally we need to know where in the array to begin.
This is a proposal with ES5 method with Array#some.
The code gets the first nonsparse element and the index. The iteration stops immediately with returning true in the callback:
var a = [, , 22, 33],
value,
index;
a.some(function (v, i) {
value = v;
index = i;
return true;
});
console.log(index, value);
If you find yourself needing to do manipulation of arrays a lot, you might be interested in the Underscore library. It provides utility methods for manipulating arrays, for example compact:
var yourArray = [];
yourArray[10] = "foo";
var firstValue = _.compact(yourArray)[0];
However, it does sound like you are doing something strange when you are constructing your array. Perhaps Array.push would help you out?