Min_by, max_by equivalent functions in javascript
To use this in the same way as Ruby, that is, call it on an array:
Array.prototype.minBy = function(lambda) {
var lambdaFn;
if (typeof(lambda) === "function") {
lambdaFn = lambda;
} else {
lambdaFn = function(x){
return x[lambda];
}
}
var mapped = this.map(lambdaFn);
var minValue = Math.min.apply(Math, mapped);
return this[mapped.indexOf(minValue)];
}
So the ruby example becomes:
['albatross', 'dog', 'horse'].minBy(function(x){return x.length }) // = 'dog'
or:
['albatross', 'dog', 'horse'].minBy("length") // = 'dog'
source to share
Chris's solution goes through the array three times; if the array is small, that's fine, but it's not ideal. You can use reduce
to get this down to one pass (with any version of the Schwartz transform):
Array.prototype.minBy = function(fn) { return this.extremumBy(fn, Math.min); };
Array.prototype.maxBy = function(fn) { return this.extremumBy(fn, Math.max); };
Array.prototype.extremumBy = function(pluck, extremum) {
return this.reduce(function(best, next) {
var pair = [ pluck(next), next ];
if (!best) {
return pair;
} else if (extremum.apply(null, [ best[0], pair[0] ]) == best[0]) {
return best;
} else {
return pair;
}
},null)[1];
}
What works as advertised:
['albatross', 'dog', 'horse'].minBy( function(s) { return s.length; } )
// => "dog"
['albatross', 'dog', 'horse'].maxBy( function(s) { return s.length; } )
// => "albatross"
source to share
An example min_by
in the documentation is in the following example:
a = %w(albatross dog horse)
a.min_by {|x| x.length } #=> "dog"
So, we can roughly translate this to JavaScript as:
var arr = ['albatross', 'dog', 'horse'];
function minBy(arr) {
var result = arr.map(function (el) { return el.length; });
var min = Math.min.apply(null, result);
return arr[result.indexOf(min)];
}
minBy(arr); // dog
max_by
would use instead Math.max.apply
.
function maxBy(arr) {
var result = arr.map(function (el) {
return el.length;
});
var min = Math.max.apply(null, result);
return arr[result.indexOf(min)];
}
maxBy(arr); // albatross
You can also change the prototype of the array to get more Rubyish.
if (!('minBy' in Array.prototype)) {
Array.prototype.minBy = function (type) {
var result = this.map(function (el) { return el[type]; });
var min = Math.min.apply(null, result);
return arr[result.indexOf(min)];
};
}
arr.minBy('length'); // dog
source to share
Lodash has both minBy and maxBy .
From the documentation:
var objects = [{ 'n': 1 }, { 'n': 2 }];
_.minBy(objects, function(o) { return o.n; }); // => { 'n': 1 }
// The '_.property' iteratee shorthand.
_.minBy(objects, 'n'); // => { 'n': 1 }
_.maxBy(objects, function(o) { return o.n; }); // => { 'n': 2 }
source to share