57

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"><a href="#">Product</a></li>
<li data-price="31.00"><a href="#">Product</a></li>
<li data-price="19.38"><a href="#">Product</a></li>
<li data-price="20.00"><a href="#">Product</a></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 :)

RJB
  • 669
  • 1
  • 8
  • 13

8 Answers8

173

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
TheCarver
  • 19,391
  • 25
  • 99
  • 149
Serg Hospodarets
  • 4,658
  • 4
  • 25
  • 31
  • 2
    I used `Math.max.apply(null,_array)` and it worked fine. Any reason not to do it that way? – Buttle Butkus Sep 24 '14 at 23:17
  • @ButtleButkus you can use `null` without any problem for the current case. Mozilla guys also use it as first param in [their examples at MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Using_apply_and_built-in_functions): `Math.max.apply(null, numbers);` – Serg Hospodarets Sep 25 '14 at 22:20
  • From ES6, you can use spreading of array: ```Math.max(...array);``` – krmld Sep 04 '17 at 11:06
12

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 });
Andreas Wong
  • 59,630
  • 19
  • 106
  • 123
  • surely you have to order the list somewhere to assume the first is cheapest and last is most expensive? – Jamiec Aug 16 '12 at 10:37
  • 1
    +1 for clear solution. at first i couldn't find `sort()` in your answer. so made comment near code – xkeshav Aug 16 '12 at 10:41
  • Your edit makes no sense, you're using `parseFloat` before adding to the array, so sort would automatically use numeric sorting rather than string. – Jamiec Aug 16 '12 at 10:44
  • @Jamiec did you test your comment? http://jsfiddle.net/9H2xg/1/. Or did I miss something here? :( I was also assuming the same way as you did – Andreas Wong Aug 16 '12 at 10:48
  • @Jamiec here's all the test, please tell me if I got it wrong. http://jsfiddle.net/9H2xg/10/ – Andreas Wong Aug 16 '12 at 10:52
  • @SiGanteng - Magic. Thanks fellers, much appreciated. – RJB Aug 16 '12 at 10:54
  • No, you're absolutely right, my mistake. Totally weird though and not how i'd intuatively thought it would work. – Jamiec Aug 16 '12 at 10:54
  • 1
    I almost entirely agree with this, but I did a quick [jsperf](http://jsperf.com/max-min-vs-sort) test, and for arrays with length of more than 10 values, it is a bunch quicker to use `Math.max.apply(Math, arr)` and `Math.min.apply(Math, arr)` respectively than to actually sort the whole array? Any bigger than that and `max` or `min` win by a long way. And personally I think it's clearer as to what is happening. – phenomnomnominal Aug 16 '12 at 11:00
  • Just a note: the sort function has an extra '}' at the end which needs to be replaced with a ')'. – Flipper Jul 17 '13 at 23:13
  • Sorting the whole array in worst case will be `n*n - n` more expensive than a regular search of a min or max value. – romaroma Feb 17 '18 at 11:04
11

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);
4
arr = [9,4,2,93,6,2,4,61,1];
ArrMax = Math.max.apply(Math, arr);
fedorqui
  • 275,237
  • 103
  • 548
  • 598
3

if you have "scattered" (not inside an array) values you can use:

var max_value = Math.max(val1, val2, val3, val4, val5);
rvandoni
  • 3,297
  • 4
  • 32
  • 46
1

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

Prince Sodhi
  • 2,845
  • 2
  • 21
  • 35
1

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>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
0

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.
Sasi Kumar M
  • 2,440
  • 1
  • 23
  • 23