Fast JavaScript Max/Min
ejohn.org
ejohn.org
Array.prototype.min = function() {
var increment = 50000;
if(this.length > increment){
var reduced_array = [];
for(var i=0;i<this.length;i+=increment) {
reduced_array.push(Math.min.apply(Math,
this.slice(i,i+increment-1)));
} }else {
return Math.min.apply(Math, this);
}
return reduced_array.min();
};
Array.prototype.max = function(array) { var increment = 50000;
if(this.length > increment){
var reduced_array = [];
for(var i=0;i<this.length;i+=increment) {
reduced_array.push(Math.max.apply(Math, this.slice(i,i+increment-1)));
}
}else {
return Math.max.apply(Math, this);
}
I'm sure someone can suggest a better way.Javascript really isn't a great choice of language for big processing tasks; stuff like that should be moved away where possible (granted it isn't always an option).
These are the results on FF 3.6.16 on my desktop:
~33.5 ops/sec (million test, using Array.min.apply)
~57.0 o/s (with index var)
~86.5 o/s (without index var)
I'm a little surprised it makes that much difference (I assumed the two set operations, one of which I removed, would be less significant than that in the execution timings compared to the array object lookup in the comparison, given JS arrays aren't actually arrays strictly speaking). The difference may be less significant (zero, in fact) with a JS engine that does dead-code analysis that successfully works out that min_i is set in the loop but otherwise never used.That's a pretty big difference, and I wouldn't have expected that much of a difference for assigning one extra variable in the loop.
[0] http://stackoverflow.com/questions/5020954/adding-functions-...
as Underscore.js do this:
_.max = function(obj, iterator, context) {
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
var result = {computed : -Infinity};
each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value;
computed >= result.computed && (result = {value : value, computed : computed});
});
return result.value;
};
_.min = function(obj, iterator, context) {
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
var result = {computed : Infinity};
each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value;
computed < result.computed && (result = {value : value, computed : computed});
});
return result.value;
};
While John do that: Array.max = function( array ){
return Math.max.apply( Math, array );
};
Array.min = function( array ){
return Math.min.apply( Math, array );
};I remember running into this in real-world code, trying to calculate the brightest pixel in a <canvas> imageData array.
That's four years ago.
That's 2 hours ago.
I guess he means fastest code to write, not the fastest code to run. If you have, say, a million numbers, I'd try doing this using concurrency. If there are two CPUs (or cores), find the maximum in the bottom half of the array and the maximum in the top half in parallel. Then return the maximum of the two maximums.
I don't know much JavaScript - does it have built-in support for concurrency?