Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the elegant way to get the latest date from array of objects in client side?

I use angularjs in project.

I get array of objects from the server. Each object contains few properties and one of them is date property.

Here is the Array (in json) that I get from server:

[
  {
    "Address": 25,
    "AlertType": 1,
    "Area": "North",
    "MeasureDate": "2019-02-01T00:01:01.001Z",
    "MeasureValue": -1
  },
  {
    "Address": 26,
    "AlertType": 1,
    "Area": "West",
    "MeasureDate": "2016-04-12T15:13:11.733Z",
    "MeasureValue": -1
  },
  {
    "Address": 25,
    "AlertType": 1,
    "Area": "North",
    "MeasureDate": "2017-02-01T00:01:01.001Z",
    "MeasureValue": -1
  }
          .
          .
          .
]

I need to get the latest date from the array.

What is the elegant way to get the latest date from array of objects?

like image 973
Michael Avatar asked Apr 12 '16 15:04

Michael


People also ask

How can I find and update values in an array of objects?

To update an object's property in an array of objects, use the map() method to iterate over the array. On each iteration, check if the current object is the one to be updated. If it is, modify the object and return the result, otherwise return the object as is.


4 Answers

A clean way to do it would be to convert each date to a Date() and take the max

ES6:

new Date(Math.max(...a.map(e => new Date(e.MeasureDate))));

JS:

new Date(Math.max.apply(null, a.map(function(e) {
  return new Date(e.MeasureDate);
})));

where a is the array of objects.

What this does is map each of the objects in the array to a date created with the value of MeasureDate. This mapped array is then applied to the Math.max function to get the latest date and the result is converted to a date.

By mapping the string dates to JS Date objects, you end up using a solution like Min/Max of dates in an array?

--

A less clean solution would be to simply map the objects to the value of MeasureDate and sort the array of strings. This only works because of the particular date format you are using.

a.map(function(e) { return e.MeasureDate; }).sort().reverse()[0]

If performance is a concern, you may want to reduce the array to get the maximum instead of using sort and reverse.

like image 143
arcyqwerty Avatar answered Oct 10 '22 00:10

arcyqwerty


Further to @Travis Heeter's answer, this returns the object that contains the latest date:

array.reduce((a, b) => (a.MeasureDate > b.MeasureDate ? a : b));

A more robust solution perhaps might be convert the strings into Date objects every time. Could be noticeably slower if dealing with (very) large arrays:

array.reduce((a, b) => {
  return new Date(a.MeasureDate) > new Date(b.MeasureDate) ? a : b;
});
like image 24
Yorkshireman Avatar answered Oct 10 '22 01:10

Yorkshireman


If you want to get the whole Object, not just the date...

If OP's array of Objects was assigned to a this is how you get the Object with the most recent date:

var mostRecentDate = new Date(Math.max.apply(null, a.map( e => {
   return new Date(e.MeasureDate);
})));
var mostRecentObject = a.filter( e => { 
    var d = new Date( e.MeasureDate ); 
    return d.getTime() == mostRecentDate.getTime();
})[0];
  1. a.map gets the dates from the array of objects.
  2. new Date is applied to each date, making Date Objects
  3. Math.max.apply finds the most recent
  4. We have found the most recent Date, now we need the object.
  5. a.filter loops through the original a array.
  6. We need some way to compare dates, so we use .getTime(), which returns the number of milliseconds since 01/01/1970. This will account for time - if it's defined - as well as date.
  7. When the correct date is found, true is returned, and .filter gives us just that object.

Note: This solution is an extension of @archyqwerty's answer above. Their solution gave only the most recent date from an array of objects, this solution gives you the whole Object that the date was a member of.

like image 24
Travis Heeter Avatar answered Oct 10 '22 01:10

Travis Heeter


Modification to Anton Harald's answer: The array I have uses ModDate instead of MeasureDate. I am choosing the most recent date. This works.

  getLatestDate(xs) {
   if (xs.length) {
   return xs.reduce((m,v,i) => (v.ModDate > m.ModDate) && i ? v : m).ModDate;
  }
}

m = accumulator, v = current , i = index

Environment: TypeScript, ES6

like image 8
Larry Popiel Avatar answered Oct 10 '22 01:10

Larry Popiel