7

I know this gets asked again and again but hear me out - this question is slightly different.

I can get a max or min from a 1D array like this:

var w_max = Math.max.apply(Math, myArray); 
var w_min = Math.min.apply(Math, myArray); 

But my array is of the type:

[[[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]]]
//max = 219.9, min = 5.12

and I need to get min and max of the second value, with the first value being an index of sorts. I've tried

myArray[][], myArray[0][0], myArray[[1]] 

and more. Console logging shows I'm getting NaN or -Infinity!!

Subjective Effect
  • 1,465
  • 2
  • 17
  • 37

9 Answers9

17

You can map the array to the second values of the elements:

var arr = [[[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]]];
var values = arr[0].map(function(elt) { return elt[1]; });
var max = Math.max.apply(null, values);
var min = Math.min.apply(null, values);
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 2
    @Aheinlein - Thanks. It's probably nowhere near as efficient as explicitly looping and testing (since it involves three iterations plus constructing a new array instead of a single iteration), but unless its a gigantic array and/or this is being done a huge number of times, the performance penalty will be negligible. There's a lot to be said for readability and maintainability. – Ted Hopp Apr 30 '14 at 20:23
  • Thanks for the reply Ted Hopp. You've answered my question in the simplest way. Fwiw - my array will only ever have a maximum of 365 elements (and usually less) as the code only looks back one year. – Subjective Effect May 01 '14 at 05:28
12

I really admired the sleek readability of @TedHopp 's solution -- so much so that I decided to adapt it into a function. The practicality of the function is still yet to be seen, but I liked the idea of being able to identify the min / max of a specified index within a 2D array.

function getMinMaxOf2DIndex (arr, idx) {
    return {
        min: Math.min.apply(null, arr.map(function (e) { return e[idx]})),
        max: Math.max.apply(null, arr.map(function (e) { return e[idx]}))
    }
} 

getMinMaxOf2DIndex() takes two parameters, arr -- an array, and idx the index of the values to compare.

Usage Examples:

// using the OP's array as an example
var array = [[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]];

getMinMaxOf2DIndex(array, 0); // {min: 1, max: 6}
getMinMaxOf2DIndex(array, 1); // {min: 5.12, max: 219.9}

// and so on...
var array = [[1, 9, 6 , 3], [2, 4, 7, 2], [6, 5, 9, 4]];
getMinMaxOf2DIndex(array, 2); // {min: 1, max: 6}
getMinMaxOf2DIndex(array, 3); // {min: 6, max: 9}
bartlb
  • 316
  • 1
  • 5
  • I really admire your solution and if I could tick two answers I'd tick your too. But Ted came up with it first. I really like your adaptation of his solution. – Subjective Effect May 01 '14 at 05:31
  • 1
    I like this generalization as well. +1. However, I'd suggest using a local variable to store the result of `arr.map(...)`. There's no reason to do all the work twice of constructing an array of the values of interest. – Ted Hopp May 01 '14 at 05:54
  • it will cause range error :: Maximum call stack size exceeded – user889030 Mar 06 '17 at 09:38
7

for big 2D arrays use this avoid function.prototype.apply as in above almost all answers i can see it. because it can handle only limited amount of array length .

function MaxMin2dray(arr, idx){
    var max = Number.MIN_VALUE;
    var min = Number.MAX_VALUE;
     arr.forEach(function(e) {
     if (max < e[idx]) {
      max = e[idx];
    }
    if (min > e[idx]) {
      min = e[idx];
    }
  });
  return {max: max, min: min};
}
user889030
  • 4,353
  • 3
  • 48
  • 51
  • 1
    This answer is the most efficient because it does not create additional arrays and performs only 1 iteration. Best solution here +1 – Adam Salma Jun 09 '20 at 07:14
  • Great! I see it doesn't work when the index passed is a date, which is what I'm after now. – onit Aug 18 '22 at 19:21
5

In ES6 you can use spread operator:

var max = Math.max(...arrayOfValues);

Working example:

var arr = [[[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]]];

var v = arr[0].map(e => e[1]);

var max = Math.max(...v);
var min = Math.min(...v);

console.log('max: ' + max);
console.log('min: ' + min);
isvforall
  • 8,768
  • 6
  • 35
  • 50
1

If you are saying it is 2D array then it should have one less []

var myArray = [[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]];
var w_max=+Infinity;
var w_min=-Infinity;

for(var i=0;i< myArray.length;i++){
    elementArray = myArray[i];
    if(w_max < Math.max.apply(Math, elementArray)){
        w_max = Math.max.apply(Math, elementArray);
    } 
    if (w_min > Math.min.apply(Math, elementArray)){
        w_min = Math.min.apply(Math, elementArray);
        }
}
Ashish
  • 14,295
  • 21
  • 82
  • 127
0

That array you have in the post is interesting, but this works for it.

var array = [[[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]]];
function getMax(a){
    var max = a[0][0][1];
    for(var i = 0; i< a[0].length; i++){
        if(a[0][i][1] > max)
            max = a[0][i][1];
    }
    return max;
}
Aheinlein
  • 480
  • 2
  • 7
  • 19
  • If the array was supposed to be [[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]] (one less []) then you can use the same, but remove the [0]. it would be a[0][1] and a[i][1] – Aheinlein Apr 30 '14 at 20:09
0
var list = [
  [1, 112.0],
  [2, 5.12],
  [3, 113.1],
  [4, 33.6],
  [5, 85.9],
  [6, 219.9]
];

function getMinMax(list) {

  var min = +Infinity;
  var max = -Infinity;

  for (var i = 0; i < list.length; i++) {
    var touple = list[i];

    var val = touple[1];
    console.log(touple);
    console.log(val);

    min = Math.min(min, val);
    max = Math.max(max, val);
  }

  return {
    min: min,
    max: max
  };

}

console.log(getMinMax(list));
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
0

You can loop through the first array (the only one here) with a forEach:

var A= [
    [[1, 112.0], [2, 5.12], [3, 113.1], [4, 33.6], [5, 85.9], [6, 219.9]]
];
var mm= [Infinity, -Infinity];

A[0].forEach(function(itm){
    var n= itm[1];
    if(n<mm[0]) mm[0]= n;
    if(n>mm[1]) mm[1]= n;   
});

mm

/* returned value: (Array) [5.12, 219.9] */

kennebec
  • 102,654
  • 32
  • 106
  • 127
-1

The first answer is not correct!!!

let arr = [[1, 112.0],[2,5.12],[3,113.1],[4,33.6],[5,85.9],[6,219.9]];
let values = Array.concat.apply([],arr);
let max = Math.max(...values);
let min = Math.min(...values);
console.log(arr)
console.log(min)//1
console.log(max)//219.9
console.log(values)//[ 1, 112, 2, 5.12, 3, 113.1, 4, 33.6, 5, 85.9, 6, 219.9 ]
  • 1
    That's AMAZING!!!!. But, much better than a bold declaration, and a code dump, would be some explanation about why your answer is the ONE. – Stephen Rauch Jun 10 '18 at 01:42