Reputation: 2835
I have a generic list of items. Each item contains a DateTime field. I would like to find the newest item in the list using Linq in the most elegant and efficient way.
Elegance is more important than efficiency in my case, but doing this also in an efficient way would be nice.
Thank you.
After reading the answers: Here is the code (and the answer I liked):
using System.Collections.Generic;
using System.Linq;
class Item
{
public Item Date { get; set; }
public string Name { get; set; }
}
static void Main(string[] args)
{
List<Item> items = CreateItems();
Item newest;
if (items.Count == 0)
newest = null;
else
newest = items.OrderByDescending(item => item.Date).First();
}
Upvotes: 3
Views: 4814
Reputation: 15130
For elegance, i would go by sorting the set based on the datetime field and returning the first item like:
set.OrderByDescending(x => x.DateTime)
.FirstOrDefault();
This will create an in-memory representation of the sorted collection so efficiency is not that good. The most efficient solution for an unsorted set would be to loop over all items and save the newest. You can use linq for this by performing an aggregate operation which i find syntactically a mess.
Alternatively, you can store your items in a sorted collection like the SortedSet. This has a bit more complex insertion time 0(log2) instead of O(1) for most collections but it allows you to immidiatly sort on datetime and therefore selecting the newest item in O(1) rather than O(n).
Upvotes: 8
Reputation: 10351
Most of the solutions so far have to completely sort the list first (via OrderByDescending), which is unnecessary and time consuming. What you want is Jon Skeet's MoreLinq MaxBy
function. Source for MaxBy is on google code.
var newest = thelist.MaxBy(x => x.DateTimeField);
Upvotes: 7
Reputation: 2569
try this one
sortlist.OrderByDescending(a => a.timeStamp).First();
Upvotes: 0
Reputation: 13723
Try Aggregate, i.e. something like:
list.Aggregate (
DateTime.MinValue,
(lastOne, current) => current.GreaterThan (lastOne) ? current : lastOne
)
i.e. if your field is DateTimeField, you should write something like
list.Aggregate (
null,
(lastOne, current) =>
(lastOne == null) ||
current.DateTimeField.GreaterThan (lastOne.DateTimeField)
? current
: lastOne
)
Upvotes: 0
Reputation: 4340
Try that:
var newItem = myList.OrderByDescending(item => item.yourDateTimeField).First();
Upvotes: 3