Min_by, max_by equivalent functions in javascript

Is there a javascript library containing functions like min_by, max_by in Ruby that allow you to use lambda as a criterion for comparison. I have not found such things in JQuery and underscore.js.

+4


source to share


5 answers


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'

      

+1


source


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"

      

+22


source


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

      

DEMO

+1


source


I use reduce

var items = [{value: 0}];
var min = items.reduce((seed,item) => { return (seed && seed.value < item.value) ? seed : item; },null);
var max = items.reduce((seed,item) => { return (seed && seed.value > item.value) ? seed : item; },null);

      

+1


source


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 }

      

0


source







All Articles