I am creating the following array from data attributes and I need to be able to grab the highest and lowest value from it so I can pass it to another function later on.
var allProducts = $(products).children("li");
prices = []
$(allProducts).each(function () {
var price = parseFloat($(this).data('price'));
prices[price] = price;
});
console.log(prices[0]) <!-- this returns undefined
My list items look like this (I have cut down for readability):
<li data-price="29.97">Product</li>
<li data-price="31.00">Product</li>
<li data-price="19.38">Product</li>
<li data-price="20.00">Product</li>
A quick console.log on prices shows me my array which appears to be sorted so I could grab the first and last element I assume, but presently the names and values in the array are the same so whenever I try and do a prices[0], I get undefined
[]
19.38 19.38
20.00 20.00
29.97 29.97
31.00 31.00
Got a feeling this is a stupidly easy question, so please be kind :)
To get min/max value in array, you can use:
var _array = [1,3,2];
Math.max.apply(Math,_array); // 3
Math.min.apply(Math,_array); // 1
Why not store it as an array of prices instead of object?
prices = []
$(allProducts).each(function () {
var price = parseFloat($(this).data('price'));
prices.push(price);
});
prices.sort(function(a, b) { return a - b }); //this is the magic line which sort the array
That way you can just
prices[0]; // cheapest
prices[prices.length - 1]; // most expensive
Note that you can do shift() and pop() to get min and max price respectively, but it will take off the price from the array.
Even better alternative is to use Sergei solution below, by using Math.max and min respectively.
EDIT:
I realized that this would be wrong if you have something like [11.5, 3.1, 3.5, 3.7] as 11.5 is treated as a string, and would come before the 3.x in dictionary order, you need to pass in custom sort function to make sure they are indeed treated as float:
prices.sort(function(a, b) { return a - b });
Instead of .each, another (perhaps more concise) approach to getting all those prices might be:
var prices = $(products).children("li").map(function() {
return $(this).prop("data-price");
}).get();
additionally you may want to consider filtering the array to get rid of empty or non-numeric array values in case they should exist:
prices = prices.filter(function(n){ return(!isNaN(parseFloat(n))) });
then use Sergey's solution above:
var max = Math.max.apply(Math,prices);
var min = Math.min.apply(Math,prices);
if you have "scattered" (not inside an array) values you can use:
var max_value = Math.max(val1, val2, val3, val4, val5);
arr = [9,4,2,93,6,2,4,61,1];
ArrMax = Math.max.apply(Math, arr);
use this and it works on both the static arrays and dynamically generated arrays.
var array = [12,2,23,324,23,123,4,23,132,23];
var getMaxValue = Math.max.apply(Math, array );
I had the issue when I use trying to find max value from code below
$('#myTabs').find('li.active').prevAll().andSelf().each(function () {
newGetWidthOfEachTab.push(parseInt($(this).outerWidth()));
});
for (var i = 0; i < newGetWidthOfEachTab.length; i++) {
newWidthOfEachTabTotal += newGetWidthOfEachTab[i];
newGetWidthOfEachTabArr.push(parseInt(newWidthOfEachTabTotal));
}
getMaxValue = Math.max.apply(Math, array);
I was getting 'NAN' when I use
var max_value = Math.max(12, 21, 23, 2323, 23);
with my code
Find largest and smallest number in an array with lodash.
var array = [1, 3, 2];
var func = _.over(Math.max, Math.min);
var [max, min] = func(...array);
// => [3, 1]
console.log(max);
console.log(min);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
If there exists requirement to find solution without using Math library, or Sorting logic, the below solutions might help.
To find the max value in javascript,
var max = -Infinity;
for (var i = 0; i < arr.length; ++i) {
if (arr[i] < max) continue;
if (arr[i] > max) {
max = arr[i];
}
}
return max;
To find the min value,
var min = +Infinity;
for (var i = 0; i < arr.length; ++i) {
if (arr[i] > min) continue;
if (arr[i] < min) {
min = arr[i];
}
}
return min;
To find all the occurrences of max values, (alter the comparisons to get all min values)
var max = -Infinity, result = [];
for (var i = 0; i < arr.length; ++i) {
if (arr[i] < max) continue;
if (arr[i] > max) {
result = [];
max = arr[i];
}
result.push(max);
}
return result; // return result.length to return the number of occurrences of max values.
Related
I want to find all possible arrays -of non-negative integers- of size L that sum up to -at most- N in JavaScript:
function findArrays(size, maxSum){}
Example input: findArrays(3, 2)
Example output:
[[0,0,0], [0,0,1], [0,0,2], [0,1,0], [0,1,1], [0,2,0], [1,0,0], [1,0,1], [1,1,0], [2,0,0]]
What I tried:
I came up with this algorithm:
Starting from left, add the array members
If the sum is equal to N at slot i:
If the member at the current index is equal to N, reset all the indices up to here and increment the next slot
Otherwise: reset previous slots and increment this slot
Otherwise:
Increment the first available slot
My code:
let getNextArray = (r,L,N)=>{
let sum=0, ind=0, i;
for(i=0; i<L; i++){
sum += r[i];
if(sum===N){
ind = i + (r[i]===N?1:0);
break;
}
}
r[ind]++;
for(i=0; i<ind; i++){
r[i]=0;
}
return r;
};
let findArrays=(L, N)=>{
let arrays=[],r=[],i;
for(i=0; i<L; i++){
r[i] = 0;
}
while(r[L-1]<N){
r = getNextArray(r,L,N);
arrays.push(r.slice());
}
return arrays;
}
It works for my example input, but when I call it with findArrays(5,3) it finds half (28 / 56) of the answers. Even if I made it work, I doubt it would be efficient for bigger inputs as it calculates the sum for each turn. I'm sure there is a more clever way to do it which I can't find..
Yesterday I asked a similar question which had a very good answer in terms of efficiency, but I realized I need fixed sized arrays. Apologies for the similar question but maybe it will help someone else one day :)
I could also use a method findArrays(size, sum) and iterate it with sums 1:N, unfortunately I don't know how to do that either.
You could modify trincot's solution with a small filter at the end:
function findArrays(maxSize, maxSum) {
let arr = [];
let result = []; // <--- will collect all the subarrays
function recur(maxSum) {
let k = arr.length;
result.push([...arr]);
if (k === maxSize) return;
for (let i = 0; i <= maxSum; i++) {
arr[k] = i;
recur(maxSum - i);
}
arr.length = k;
}
recur(maxSum);
return result.filter(({ length }) => length == maxSize);
}
// demo
for (let arr of findArrays(3, 2))
console.log(JSON.stringify(arr));
Here's a non-yielding version of a recursive function which will give the results you want. It figures out all possible values at the current level (0..maxSum) and then appends them to all possible results for arrays with size-1:
const findArrays = (size, maxSum) => {
let possibles = Array.from({
length: maxSum + 1
}, (_, i) => i);
if (size == 1) return possibles;
let result = [];
possibles.forEach(p => {
findArrays(size - 1, maxSum - p).forEach(a => {
result.push([p].concat(a));
});
});
return result;
}
console.log(findArrays(3, 2));
Here's a working algorithm that finds the third smallest number in a given set of numbers.
I was looking for another solutions to the given requirement with less time complexity.
Here's the working code:
Numbers = [3,2,55,-10,-55,5,3,2,1,-5,33,9,-1,4,5];
var x = 0;
var y = 0;
function FindThirdSmallestNumber() {
for(var i=0;i<Numbers.length;i++) {
if (Numbers[i] > Numbers[i+1]) {
x = Numbers[i];
y = Numbers[i+1];
Numbers[i] = y;
Numbers[i+1] = x;
i=-1;
} else {
//
}
}
console.log(Numbers[2]);
}
FindThirdSmallestNumber();
Not sure if this is any faster but it's shorter:
//Use a custom sort function and pass it to the .sort() method
Numbers = Numbers.sort(function(x, y){ return x - y; });
if(Numbers.length > 2){
//At this point, the 3rd item in the array should be the 3rd lowest
console.log(Numbers[2]);
}else {
console.log("There are not 3 numbers in the array.");
}
One option would be to have a separate sorted array of the three smallest numbers so far. Whenever you run across a number smaller than the 3rd smallest (the last in the sorted array), reassign that 3rd index to the new number, and sort it again:
const numbers = [3, 2, 55, -10, -55, 5, 3, 2, 1, -5, 33, 9, -1, 4, 5];
const sortNumeric = (a, b) => a - b;
function FindThirdSmallestNumber(input) {
const [smallestSoFar, numbers] = [input.slice(0, 3), input.slice(3)];
smallestSoFar.sort(sortNumeric);
numbers.forEach((num) => {
if (num < smallestSoFar[2]) {
smallestSoFar[2] = num;
smallestSoFar.sort(sortNumeric);
}
});
return smallestSoFar[2];
}
console.log(FindThirdSmallestNumber(numbers));
Note that implementations that sort the whole array (as other answers do) is O(N log N), while sorting here is only ever done on an array of size 3, which is significantly less complex (O(N log 3) I think, which is equivalent to O(N))
This one should be a lot simpler. Also not sure about this being any faster but in the most simple/obvious cases less code = better performance.
I just sort the array ascending and get the value based on index. So with this code you can get any place; lowest, second lowest, third lowest, etc as long as your index does not go out of range.
const input = [3,2,55,-10,-55,5,3,2,1,-5,33,9,-1,4,5];
function getLowestByRank(data, rank) {
data.sort(function(a, b){ return a - b });
return data[rank - 1];
}
console.log(getLowestByRank(input, 3))
console.log(getLowestByRank(input, 2))
console.log(getLowestByRank(input, 4))
You can use Math.min function to determine the minimum until you find your X smallest number:
Numbers = [3,2,55,-10,-55,5,3,2,1,-5,33,9,-1,4,5];
function FindSmallestNumber(arr, limit) {
var min = '';
for(var counter = 1; counter <= limit; counter ++) {
min = Math.min.apply(Math, arr);
arr.splice(arr.indexOf(min), 1);
}
console.log(min);
}
FindSmallestNumber(Numbers, 3); //3rd smallest number
I think sorting the array is likely the fastest method, but perhaps you want avoid the built–in sort. An alternative is as Chris Li suggests: iterate over the values and just keep the 3 lowest, then return the highest of the three.
I assumed you want to avoid built-in methods, so this only uses some basic array methods and does everything else manually.
// Avoid Math.max
function getMax(arr) {
var max = -Infinity;
for (var i=0, iLen=arr.length; i<iLen; i++) {
if (arr[i] > max) max = arr[i];
}
return max;
}
// If data.length < 4, just returns largest value
// Iterates over data once
function get3rdSmallest(data) {
// Helper to insert value in order
// Expects arr to be length 3 or smaller
function insertNum(arr, num) {
if (!arr.length || num < arr[0]) {
nums.unshift(num);
} else if (num > arr[arr.length-1]) {
arr.push(num);
} else {
arr[2] = arr[1];
arr[1] = num;
}
}
var num, nums = [];
if (data.length < 4) {
return getMax(data);
}
for (var i=0, iLen=data.length; i<iLen; i++) {
num = data[i];
// Insert first 3 values sorted
if (nums.length < 3) {
insertNum(nums, num);
// If num is smaller than largest value in nums,
// remove move largest and insert num
} else if (num < nums[2]){
nums.splice(-1);
insertNum(nums, num);
}
}
// Return highest (last) value in nums
return nums[2];
}
var data = [3,2,55,-10,-55,5,3,2,1,-5,33,9,-1,4,5];
console.log(get3rdSmallest([-4,-22])); // -4
console.log(get3rdSmallest([4,0,1,7,6])); // 4
console.log(get3rdSmallest(data)); // -5
Can anyone tell me what I'm doing wrong? I am printing the array just not in the right order. How do i call it differently? This is javascript by the way.
Given an array x (e.g. [1,5, 10, -2]), create an algorithm (sets of instructions) that returns an array with the max, min, and average values ([max, min, avg]. ex [0,2,4] should return [4,0,2]).
My code:
function maxMinAvg(arr) {
var newarr= [];
var max = arr[0];
var min = arr[0];
sum = sum + arr[0];
var avg = sum/arr.length;
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
sum = sum + arr[i];
}
newarr.push([max[i],min[i],avg[i]]);
}
return newarr;
The function should look like this
function maxMinAvg(arr) {
var max = arr[0];
var min = arr[0];
var sum = arr[0]; //changed from original post
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
sum = sum + arr[i];
}
return [max, min, sum/arr.length]; //changed from original post
}
Not sure if this works but you could use the arr.sort() function to sort it and you have your min and max, then just add all values and find mean.
function maxMinMean(arr) {
arr.sort();
var sum = 0;
for (let i = 0; i<arr.length; i++){
sum = sum + +arr[i];
}
return [+arr[length - 1], +arr[0], sum / arr.length];
}
This assumes you are trying to do this with array of numbers (It will also work if the numbers in the array are stored as string)
Have not tested it but should work fine.
try this...
function maxMinAvg(arr) {
var max = arr[0];
var min = arr[0];
var sum = 0 ;
arr.forEach(function(value){
if(value > max)
max = value;
if(value < min)
min = value;
sum +=value;
})
var avg = sum/arr.length;
return [max,min,avg];
}
You already have the values min, max and avg (you have the sum so you can calculate it). Just a create a new array (not your original arr), add those values (min, max and avg) to it and return it.
Your code is not returning the values in the wrong order, it's returning the original array instead of an array with the max, min and average.
The reason that it looks like the items are in the wron g order, is that you have picked test data that happens to be similar to the result that you expect. If you pick data where the input is not so similar to the output, for example [1,2,3,4,100], you see that you get the same array back.
Just create a new array with the values and return it:
return [ max, min, avg ];
Edit:
With the new code that you posted I see some problems:
It's calculating the average before it has the sum of all items. it's just using the first item.
It doesn't initialise the sum variable, so it will contain undefined. When adding to it, the result will continue to be undefined.
The sum variable is not local, so it could interfer with other code.
It's pushing an array into the array, so you get an array or arrays as result instead of an array.
It's using the min, max and avg variables as if they were arrays when it puts them in the result.
Fixing that, you get:
function maxMinAvg(arr) {
var max = arr[0];
var min = arr[0];
var sum = arr[0];
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
sum = sum + arr[i];
}
var avg = sum / arr.length;
return [max, min, avg];
}
function maxMinMean(arr: number[]) {
if (!arr.length) return [NaN,NaN,NaN];
arr.sort((a,b)=>a-b);
return [
arr.slice(-1)[0],
arr[0],
arr.reduce((sum, x) => sum + x,0) / arr.length,
];
}
If you didn't want to modify the original array
function maxMinMean(arrIn: number[]) {
if (!arrIn.length) return [NaN,NaN,NaN];
var arr =[...arrIn].sort((a,b)=>a-b);
return [
arr.slice(-1)[0],
arr[0],
arr.reduce((sum, x) => sum + x,0) / arr.length,
];
}
If you wanted fixed point strings
function maxMinMean(arr: number[]) {
if (!arr.length) return [NaN,NaN,NaN];
arr.sort((a,b)=>a-b);
return [
arr.slice(-1)[0],
arr[0],
arr.reduce((sum, x) => sum + x,0) / arr.length,
].map(f=>f.toFixed(2));
}
A little more elegant solution, via a library:
import {map, pipe} from 'iter-ops';
import {numberStats} from './extras';
const input = [1, 5, 10, -2];
const i = pipe(input, numberStats(), map(a => [a.max, a.min, a.avg]));
console.log(...i); //=> [ 10, -2, 3.5 ]
The above solution is based on iter-ops library, plus custom numberStats operator, from the extras.
I need to calculate min/max of large array. I know about Math.max.apply(), but on large arrays it fails with Stack overflow exception. Any simple solutions?
Sort the array by using sort() method it sorts array by using quicksort algorithm
Since array is sorted in ascending order then the last element is the max
var arr = [1,4,6,4, ...];
arr.sort((a, b) => a - b);
var max = arr[arr.length - 1];
Array.prototype.min = function() {
var r = this[0];
this.forEach(function(v,i,a){if (v<r) r=v;});
return r;
};
From JavaScript: min & max Array values? where other solutions from this problem are discussed
FYI: I just googled "max min large array" and found this as the first result...
Why not just loop through the entire array?
var max = Number.MIN_VALUE, min = Number.MAX_VALUE;
for (var i = 0, len=list.length; i < len; i++) {
if (list[i] > max) max = list[i];
if (list[i] < min) min = list[i];
}
Edit:
For max:
if (typeof Array.prototype.GetMax === "undefined") {
Array.prototype.GetMax = function() {
var max = Number.MAX_VALUE;
for (var i = 0, len=this.length; i < len; i++) {
if (this[i] > max) max = this[i];
}
return max;
}
}
For min:
if (typeof Array.prototype.GetMin === "undefined") {
Array.prototype.GetMin = function() {
var min = Number.MIN_VALUE;
for (var i = 0, len=this.length; i < len; i++) {
if (this[i] < min) min = this[i];
}
return min;
}
}
For both:
if (typeof Array.prototype.GetMaxMin === "undefined") {
Array.prototype.GetMaxMin = function() {
var max = Number.MIN_VALUE, min = Number.MAX_VALUE;
for (var i = 0, len=this.length; i < len; i++) {
if (this[i] > max) max = this[i];
if (this[i] < min) min = this[i];
}
return { Max: max, Min: min};
}
}
Should I assume you have thought of this:
var maxSoFar = -9999999;
for (var i = 0; i < array.length ; ++i) {
if (array[i] > maxSoFar) {
maxSoFar = array[i];
}
... similar for minSoFar ...
}
try this
var arr = [];
for(var i=1000000;i>0;i--)
{
arr.push(i);
}
//we create a copy of the original array through arr.concat() since we do not want to change the original sorting order of the array
//we pass a function in the sort method as by default it sorts alphabetically instead of numerically. So 99 will be smaller than 100.
var arrMaxMin = arr.concat().sort(function(a,b){return a-b});
arrMaxMin[0]; //min
arrMaxMin[arrMaxMin.length - 1]; //max
Hey why dont you slice your array into smaller arrays then on that arrays you can easily use Math.max.apply(Math,individual arrays).But remember to reinitialize all subarrays back to null so as to get the memory back once desired max value is obtained
This is exactly what reduce is for:
function max(arr) {
if (arr.length === 0) {
return NaN // or whatever answer you want for an empty array, or throw an error.
}
return arr.reduce((a, b) => Math.max(a, b), -Infinity)
}
console.log(max([...new Array(100000).keys()]))
(note that [...new Array(100000).keys()] is just a fancy way in a modern browsers to make a huge array of the numbers 0 to 999999. The max function itself will run in anything made in the last 20 years.)
You can also reduce it to this one-liner:
arr.reduce((cur, val, i) => i === 0 ? val : Math.max(cur, val), NaN)
here NaN is the value you get back if the array is empty
Or even
arr.reduce((a, b) => Math.max(a, b), -Infinity)
although this will return -Infinity for an empty array.
Finally, it may be tempting to just do:
arr.reduce(Math.max, -Infinity) //don't do this!!
but this won't work. This is because reduce calls it's function (Math.max) with 4 parameters, one of which is the original array, so a Math.max on those will always result in a NaN.
I have a array like
arr[1] = 234;
arr[2] = 345;
...
arr[40] = 126;
How can I get the index of the element with the highest value without reiterating the array?
You can apply Math.max and pass the array as its arguments-
arr.indexOf(Math.max.apply(window,arr))
But now Math.max is doing the iterating, just as sort would do.
Somebody has to look at each item in an unsorted array...
With jQuery, is as simple as:
// Get the max value from the array
maxValue = Math.max.apply(this, arr);
// Get the index of the max value, through the built in function inArray
$.inArray(maxValue,arr);
If the array is not ordered you cannot do this without iterating.
Get the array key with the highest value in javascript
var cars = ["Saab", "Volvo", "BMW"];
var max_car_result = cars[cars.length-1];
alert(max_car_result);
Try this:
var max_index = -1;
var max_value = Number.MIN_VALUE;
for(var i = 0; i < arr.length; i++)
{
if(arr[i] > max_value)
{
max_value = arr[i];
max_index = i;
}
}
You could use a function to set the variable. And keep track of the max in that function. Here's a quick example without type checking, testing, or support for removing a value.
Array.prototype.maxValue = null;
Array.prototype.setIndex = function(index, value){
this[index] = value;
if (value > this.maxValue || this.maxValue == null)
this.maxValue = value;
}
var arr = new Array();
arr.setIndex(0, 234);
arr.setIndex(1, 500);
arr.setIndex(2, -5);
var maxValue = arr.maxValue;
Obviously this is nicer if you're currently setting items like this:
var arr = new Array();
arr[0] = 1;
arr[1] = 500;
arr[2] = 2;
Rather than this:
var arr = { 1, 500, 2 };
The downside is its not natural and requires you to use function to get the correct results.
Keep the array sorted or use a heap.
Otherwise iterate. Even if you found some trick to do it it would still require iterating underneath so why not iterate?
If it seems like too much code, put it in a separate routine.
Two solution: to sort descending order and get the first element or:
function bigger(array) {
if (array.length < 1) {
return -1;
}
bigger = 0;
for(var i=1; i<array.length;i++ ) {
if(array[i] > array[bigger]) {
bigger = i;
}
}
return bigger;
}
you cold optimize using two variables, one for the position and other for the content.
Either you will have iteration somewhere (in your code or in JQuery.each()) or you can define something like this:
Array.prototype.mpush = function(v)
{
var maxv = this.maxValue || Number.MIN_VALUE;
if( v > maxv ) { this.maxValue = v; this.maxIndex = this.length; }
this.push(v);
}
and use that arr.mpush(v) to populate your array. In this case the array will have maxIndex property.
Is old question but here is an my simple emulation of PHP script max() made in javascript:
function max(array){
if(Object.prototype.toString.call( array ) === '[object Array]'){
return array[(array.length-1)];
}
else return 0;
}
This return value of last key in array or 0 if nothing found.
Maby someone helps.
You can use it like:
var array = ['bananaman','spiderman','ironman','superman','batman','manman'];
var getLast = max(array);
if(getLast !== 0)
alert(getLast); // manman