2

I need to perform in JavaScript what in C# would look like this:

var latest = versions.OrderByDescending( v => v.VersionNo).First();

I want this done via Math.max method and although it should be trivial task I am struggling to get it correct. I've gone through web and several questions here but can't make it work.

HarryS
  • 186
  • 1
  • 5
zmaten
  • 429
  • 4
  • 16
  • What's the datatype of `VersionNo`? You possibly have to convert it to a numeric type first before selecting the max value. – diiN__________ Aug 19 '16 at 10:44
  • @diiN_ It is a number. – zmaten Aug 19 '16 at 10:48
  • Duplicate of http://stackoverflow.com/questions/4020796/finding-the-max-value-of-an-attribute-in-an-array-of-objects – Pablo Aug 19 '16 at 10:52
  • 1
    The question you link is different since OP wants just the property not the object itself. – zmaten Aug 19 '16 at 11:01
  • I know this is an old post, but I wanted to document this for future readers. In C# getting the max object by it's property value using OrderBy or OrderByDecending is the least efficient way to get the result. You should instead use Aggregate which is the C# alternative to JavaScript's reduce(). `var latest = version.Aggregate((l, e) => e.VersionNo > l.VersionNo ? e : l);` Why? Because OrderBy must sort the array vs. aggregate doing the same operation in a single pass. – Ed Charbeneau Mar 22 '18 at 16:12

2 Answers2

14

So basically, you want to find the object in versions with the highest VersionNo.

Sounds like a job for Array#reduce:

var latest = versions.reduce(function(l, e) {
  return e.VersionNo > l.VersionNo ? e : l;
});

var versions = [
  {VersionNo: 3},
  {VersionNo: 7},
  {VersionNo: 1}
];

var latest = versions.reduce(function(l, e) {
  return e.VersionNo > l.VersionNo ? e : l;
});
console.log(latest);

When you call it as above (with just one argument, the callback to use), Array#reduce calls your callback with the first two entries, and then again for each subsequent entry with the first argument being the return value of the previous call and the second being the next entry in the array. The result is the final return value of the last callback.

Clear as mud? That means if you call it on an array with [1, 2, 3, 4] your callback will be called with 1, 2, then r, 3 where r is whatever it returned, then r, 4 where r is whatever it returned the last time. (If you give a second argument to reduce, it uses that as the initial value for r and just does r, 1, then r, 2, ...)

So in the above, we return the object with the higher VersionNo of the two arguments from the callback, which will eventually give us the first one with the highest value. (I say "first one" because if you have more than one with the same value, we'll take the first.)

Or in ES2015+:

let latest = versions.reduce((l, e) => e.VersionNo > l.VersionNo ? e : l);

let versions = [
  {VersionNo: 3},
  {VersionNo: 7},
  {VersionNo: 1}
];

let latest = versions.reduce((l, e) => e.VersionNo > l.VersionNo ? e : l);
console.log(latest);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
-1

You can get the max value of a property in an object with the following

var latest = (Math.max.apply(Math, versions.map(function(v) {
  return v.VersionNo;
})));

Documentation on .map() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

IronAces
  • 1,857
  • 1
  • 27
  • 36
  • 1
    I didn't (took me a while to figure out why someone else did), but I'll note that `latest` will be the highest value of `VersionNo`, not a reference to the object from `versions` with the highest value for that property (which is what the OP C# code does). – T.J. Crowder Aug 19 '16 at 10:54
  • @DanielShillcock I didn't too. But as T.J. Crowder says this brings different results. – zmaten Aug 19 '16 at 13:22