views:

218

answers:

3

here is the code....:

 var minX = minY = maxX = maxY = 0;

 for(var i=0; i<objArray.length; i++){
  if(objArray[i].x < minX){
   minX = objArray[i].x;
  }else if(objArray [i].x > maxX){
   maxX = objArray[i].x;
  }
  if(objArray[i].y < minY){
   minY = objArray[i].y;
  }else if(objArray [i].y > maxY){
   maxY = objArray[i].y;
  }
 }

It works. but I think it is not so elegant to do so, don't u agree? it is only some sample logic, but it use up to 10 lines of code. What do you think?

+6  A: 

You could use Math.min and Math.max:

var minX = minY = Number.POSITIVE_INFINITY,
    maxX = maxY = Number.NEGATIVE_INFINITY;

for(var i=0; i<objArray.length; i++){
  minX = Math.min(objArray[i].x, minX);
  minY = Math.min(objArray[i].y, minY);
  maxX = Math.max(objArray[i].x, maxX);
  maxY = Math.max(objArray[i].y, maxY);
}

For loop speed optimization you could store the length to only calculate it once:

for(var i=0, len = objArray.length; i<len; i++){
  //...
}

Check this article for more information about loop optimization.

Another approach, just for "functional fun", since I wouldn't recommend it for performance, could be to separate the x and y values to two arrays using Array.map, and then call the min and max functions with apply:

var allX = objArray.map(function (o) { return o.x; });
var allY = objArray.map(function (o) { return o.y; });

minX = Math.min.apply(Math, allX);
minY = Math.min.apply(Math, allY);
maxX = Math.max.apply(Math, allX);
maxY = Math.max.apply(Math, allY);

How this works?

The apply function is used to call another function, with a given context and arguments, provided as an array. The min and max functions can take an arbitrary number of input arguments: Math.max(val1, val2, ..., valN)

So if we call:

Math.min.apply(Math, [1,2,3,4]);

The apply function will execute:

Math.min(1,2,3,4);

Note that the first parameter, the context, is not important for these functions since they are static, they will work regardless of what is passed as the context.

CMS
needs another edit as of right now - still, nice work.
Andy Gaskell
@Andy: Edited, thanks!
CMS
+1  A: 

All the answers so far seem to be using uninitialized variables (minX, etc) in comparisons. Here is a functional, elegant solution:

var minX = anarray.reduce( function(a,b) { return {x : Math.min(a.x,b.x)};}).x;
var minY = anarray.reduce( function(a,b) { return {y : Math.min(a.y,b.y)};}).y;
var maxX = anarray.reduce( function(a,b) { return {x : Math.max(a.x,b.x)};}).x;
var maxY = anarray.reduce( function(a,b) { return {y : Math.max(a.y,b.y)};}).y;

Look here for an explanation of the reduce function and how to enable it in browsers that do not support it natively.

postfuturist
+2  A: 

it use up to 10 lines of code.

LoC is not a measure of optimisation, however.

I tested the above algorithms in Firefox 3.5. (See below for test case.)

Your original code (methodA) was nearly twice as fast as CMS's (methodB)! The use of Math.min makes his version way more readable, and in most circumstances that is what's important. But it does introduce more lookups and function calls, and that slows it down.

The ‘functional fun’ version (methodC) was actually considerably faster than either version! This was a surprise for me since this version has to build up two temporary arrays, but it seems the nice use of apply() to do all the comparisons in one go makes up for that. This is, however, on Firefox, where there is a native implementation of Array.map(). Browsers like IE that do not have this functionality require hacking a JavaScript version into the Array prototype, which made methodC as slow as methodB for me.

Steveth's alternative functional version was, as expected, very slow; all those temporary objects take a toll.

In the end the fastest I managed was by taking the original methodA and tweaking it to remove the per-loop .length access, and micro-optimise the multiple property accesses. Surprisingly this (methodE) knocked quite a bit off.

However, all this is usually very browser-specific. I only tested on one browser; you may get different results on others. Usually micro-optimisation does not pay off and you are better off going with the most readable option.

<script type="text/javascript">
    var objArray= [];
    for (var i= 0; i<1000000; i++) {
        objArray.push({'x': Math.floor(Math.random()*100000), 'y': Math.floor(Math.random()*100000)});
    }

    function methodA() {
        var t= new Date();
        var minX = minY = maxX = maxY = 0;
        for(var i=0; i<objArray.length; i++){
                if(objArray[i].x < minX){
                        minX = objArray[i].x;
                }else if(objArray [i].x > maxX){
                        maxX = objArray[i].x;
                }
                if(objArray[i].y < minY){
                        minY = objArray[i].y;
                }else if(objArray [i].y > maxY){
                        maxY = objArray[i].y;
                }
        }
        alert(new Date()-t);
    }
    function methodB() {
        var t= new Date();
        var minX = minY = Number.POSITIVE_INFINITY,
            maxX = maxY = Number.NEGATIVE_INFINITY;
        for(var i=0; i<objArray.length; i++){
          minX = Math.min(objArray[i].x, minX);
          minY = Math.min(objArray[i].y, minY);
          maxX = Math.max(objArray[i].x, maxX);
          maxY = Math.max(objArray[i].y, maxY);
        }
        alert(new Date()-t);
    }
    function methodC() {
        var t= new Date();
        var allX = objArray.map(function (o) { return o.x; });
        var allY = objArray.map(function (o) { return o.y; });

        minX = Math.min.apply(Math, allX);
        minY = Math.min.apply(Math, allY);
        maxX = Math.max.apply(Math, allX);
        maxY = Math.max.apply(Math, allY);
        alert(new Date()-t);
    }
    function methodD() {
        var t= new Date();
        var minX = objArray.reduce( function(a,b) { return {x : Math.min(a.x,b.x)};}).x;
        var minY = objArray.reduce( function(a,b) { return {y : Math.min(a.y,b.y)};}).y;
        var maxX = objArray.reduce( function(a,b) { return {x : Math.max(a.x,b.x)};}).x;
        var maxY = objArray.reduce( function(a,b) { return {y : Math.max(a.y,b.y)};}).y;
        alert(new Date()-t);
    }
    function methodE() {
        var t= new Date();
        var minX = minY = maxX = maxY = 0;
        var o, v;
        for (var i=objArray.length; i-->0;) {
            o= objArray[i];
            v= o.x;
            if (v<minX) minX= v;
            if (v>maxX) maxX= v;
            v= o.y;
            if (v<minY) minY= v;
            if (v>maxY) maxY= v;
        }
        alert(new Date()-t);
    }
</script>
<button onclick="methodA()">A</button>
<button onclick="methodB()">B</button>
<button onclick="methodC()">C</button>
<button onclick="methodD()">D</button>
<button onclick="methodE()">E</button>
bobince