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!!

9 Answers 9

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);
Sign up to request clarification or add additional context in comments.

4 Comments

@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.
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.
When you say "gigantic array" how many elements are you talking about?
@Mark - That's a highly technical term that means "big enough to make a difference." The precise definition is known to only a few and is passed down from guru to guru. :) (Silliness aside, my guess is that it would probably take many thousands of elements to have a noticeable performance impact. It's easy enough to write a benchmark that would allow one to plot array size against some performance measure like execution time or memory usage.)
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}

3 Comments

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.
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.
it will cause range error :: Maximum call stack size exceeded
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};
}

2 Comments

This answer is the most efficient because it does not create additional arrays and performs only 1 iteration. Best solution here +1
Great! I see it doesn't work when the index passed is a date, which is what I'm after now.
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);

Comments

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);
        }
}

Comments

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;
}

1 Comment

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]
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));

1 Comment

Just noticed that I unnested your inner array since it was actually an array of arrays of arrays -- a 3D array, if you will.
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] */

Comments

-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 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.