10

I have an array that looks like the following:

array = [[1, 5], [4, 7], [3, 8], [2, 3],  
 [12, 4], [6, 6], [4, 1], [3, 2], 
 [8, 14]]

What I need is the largest number from the first value of the sets, so in this case 12. Looking at some examples online, the best way I saw to accomplish this is :

Math.max.apply Math, array

Problem is, this only works with single dimensional arrays. How would I impliment this for my senario? (jquery allowed)


The end solution:

It wasn't part of the question, but I needed both the min and max from the array, and that changes things a little.

    unless device.IE
        justTheDates    = magnitudeArray.map (i) -> i[0]
        @earliest       = Math.min.apply Math, justTheDates
        @latest         = Math.max.apply Math, justTheDates                 
    else
        @earliest       = magnitudeArray[0][0]
        @latest         = magnitudeArray[0][0]
        for magnitudeItem in magnitudeArray
            @earliest   = magnitudeItem[0] if magnitudeItem[0] < @earliest
            @latest     = magnitudeItem[0] if magnitudeItem[0] > @latest
Fresheyeball
  • 28,195
  • 19
  • 94
  • 160

8 Answers8

13

You can use .reduce()...

array.reduce(function(max, arr) { 
    return Math.max(max, arr[0]); 
}, -Infinity)

Here's a version that doesn't use Math.max...

array.reduce(function(max, arr) {
    return max >= arr[0] ? max : arr[0];
}, -Infinity);

...and a jsPerf test.

  • 3
    +1 For a classic fold example :). A CoffeeScript [translation](http://coffeescript.org/#try:array%20%3D%20[[1%2C%205]%2C%20[4%2C%207]%2C%20[3%2C%208]%2C%20[2%2C%203]]%0A%0Amax%20%3D%20array.reduce%20%28%28max%2C%20arr%29%20-%3E%20Math.max%20max%2C%20arr[0]%29%2C%20-Infinity%0Aconsole.log%20max): `max = array.reduce ((max, arr) -> Math.max max, arr[0]), -Infinity` – epidemian Jun 22 '12 at 04:06
  • I am seeing more votes for this answer. Would someone be interested in making a case for it OVer the one I accepted? – Fresheyeball Jun 22 '12 at 07:36
  • 1
    @Fresheyeball: I wouldn't want to say that one is better than the other. A `.reduce()` just evaluates an Array down to a single value. A `.map()` is basically a `.reduce()` that evaluates it down to a new collection. So a `.map()` behavior can be achieved using `.reduce()` like this: `array.reduce(function(arr, curr) { arr.push(curr[0]); return arr; }, [])`. And then you'd still use `Math.max.apply...`. The advantage using the `.map()` style with `.apply` is that you avoid the repeated `Math.max` calls. The advantage of reducing directly to a number is perhaps a little clarity. –  Jun 22 '12 at 12:36
  • @Fresheyeball: FYI, I posted another version that doesn't use `Math.max`, as well as a jsPerf test. –  Jun 22 '12 at 13:01
  • @amnotiam looks like neither `.map` or `.reduce` is suppored by ie8! What to do now? – Fresheyeball Jun 22 '12 at 16:06
  • @Fresheyeball: Shim it with patches from MDN. [`.map()`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map#Compatibility) [`.reduce()`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce#Compatibility) This way you can code using modern techniques immediately. –  Jun 22 '12 at 16:23
  • 1
    Interesting. Yeah I found how the shim works and just implemented a loop for ie8- – Fresheyeball Jun 22 '12 at 18:50
  • is it possible to get the other values from the 'max' value? ex: if `[8, 14]` 8 is the high value how can i get `14`? – t q Feb 20 '15 at 17:44
  • 1
    @tq: `return Math.max.apply(Math, arr.concat(max))` –  Feb 20 '15 at 21:58
8

http://jsfiddle.net/zerkms/HM7es/

var max = Math.max.apply(Math, arr.map(function(i) {
    return i[0];
}));​

So at first you use array.map() to convert the 2-dimensional array to a flat one, and after that use Math.max()

zerkms
  • 230,357
  • 57
  • 408
  • 498
  • I am not familiar with .map can you explain what is going on there? – Fresheyeball Jun 22 '12 at 03:45
  • @Fresheyeball: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map --- so it applies a callback to each element. In your case each `i` is a `[1, 5]` - array of 2 elements, and you just return first item. After `arr.map()` is applied you have another array, that contains 1st elements of each nested array – zerkms Jun 22 '12 at 03:47
  • I guess my question is ... is .map more or less efficient than a loop? – Fresheyeball Jun 22 '12 at 03:53
  • 1
    @Fresheyeball: I'm sure it is very close to it and I'm also sure it is not a thing you need to think about now. Choose the solution you can read/maintain better – zerkms Jun 22 '12 at 03:54
  • CoffeeScript often suggests node, but it might be worth noting that `Array#map` isn't supported <= IE8 – numbers1311407 Jun 22 '12 at 04:37
  • Very nice use of .map()! Thank you, sir! – Dom Oct 08 '12 at 16:54
2

A simple solution using Underscore.js' max that avoids generating an intermediate array:

max = _(array).max(_.first)[0]

(JSFiddle)

epidemian
  • 17,826
  • 3
  • 57
  • 68
  • I am NOT going to include an entire new lib just do solve this. – Fresheyeball Jun 22 '12 at 04:43
  • 1
    OK, then the other solutions will work better :). Underscore has many useful little functions that, in my experience, are used quite often; and it's only 4KB, so, if it is because of library size, you are not in danger of bloating too much when including it. – epidemian Jun 22 '12 at 04:57
1

Using a comprehension in CoffeeScript:

Math.max.apply Math, (x[0] for x in array)

Running example

jimr
  • 10,682
  • 1
  • 29
  • 31
1

Also, look at _underscore.js. Here is a link to the function _max().

  • It is simply more efficient to read, write and maintain.

The best part about _underscore is that there are about another hundred helper functions similar to _max. Like sort.

Compare the syntax below:

var sortedObject = _.sortBy(object, function(val, key, object) {
    return val;
});

They are easy to chain, and interpret! (Like Douglas Crockford might suggest)

An excellent JSFIDDLE, was provided in this post by @Raynos.

If you are consistently conducting array operations with raw JavaScript, check out _underscore.js, it can greatly simplify your code.

Hope that helps, All the best! Nash

Community
  • 1
  • 1
Jack Stone
  • 2,358
  • 1
  • 17
  • 25
  • 1
    "It is simply more efficient" --- how the library can be more efficient than the underlying language? – zerkms Jun 22 '12 at 03:59
  • Good question, more efficient to write (to read, and maintain). Thanks for the clarification @zerkms. +1. Edited. – Jack Stone Jun 22 '12 at 04:08
  • 1
    I am NOT going to include an entire new lib just do solve this. – Fresheyeball Jun 22 '12 at 04:09
  • Correct. This is for those that are "consistently conducting array operations with raw JavaScript". Some environments are such. If maintaining advanced algorithms this may be an optimization for you. It also comes with a powerful templating engine for advanced data-binding. – Jack Stone Jun 22 '12 at 04:41
  • Frankly I am not impressed with underscore. – Fresheyeball Jun 22 '12 at 04:42
  • Can you tell us of its shortcomings or downsides? With so many .js libraries, whether one is good or bad often comes down to best fit for context and environment. Hope this helps. All the best! Nash (Thanks for your assessment). – Jack Stone Jun 22 '12 at 04:44
1
Array.prototype.maxX = function(){
  return Math.max.apply(Math,this.map(function(o){return o[0];}));
};
Sarah-Jane
  • 133
  • 1
  • 4
1

I know this is an old post, but if you (or someone else) want the largest number in the whole array, try with:

var array = [[1, 5], [4, 7], [3, 8], [2, 3],  
 [12, 4], [6, 6], [4, 1], [3, 2], 
 [8, 14]];

var max = array.reduce(function (max, arr) {
    return max >= Math.max.apply(max, arr) ? max : Math.max.apply(max, arr);
}, -Infinity);
console.log(max);

In this examlpe, it will return the value 14.

0

Sample Input: largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);

function largestOfFour(arr) {

    var largest = 0;
    var largestArr = [];
    for(var i=0; i<arr.length; i++){
      for(var j=0; j<arr[i].length; j++){

        if(largest < arr[i][j]){
          largest = arr[i][j];
        }
        largestArr[i] = largest;
      }      
      largest = 0;
    }

  return largestArr;
}

You can populate largest numbers into new Array from two dim array.

dorgo
  • 3
  • 3