3

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();
}
Tal Segal
  • 2,735
  • 3
  • 21
  • 17
  • 3
    could you show us an example of what you want. Also what do **you mean** when you say newest? – gideon May 30 '12 at 05:20
  • @gideon - I have added some code, Since the answer is so simple and elegant - I have also added it. – Tal Segal May 30 '12 at 09:15
  • Possible duplicate of http://stackoverflow.com/questions/914109/how-to-use-linq-to-select-object-with-minimum-or-maximum-property-value – Steve Chambers Apr 25 '13 at 08:56

5 Answers5

8

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).

Solarcloud
  • 555
  • 1
  • 7
  • 15
Polity
  • 14,734
  • 2
  • 40
  • 40
  • Thank you. I marked it as the accepted answer because of the FirstOrDefault and the nice complexity explanation and alternatives. Cheers! – Tal Segal May 30 '12 at 06:09
  • Strange, I can not find the any OrderBy method for my Generic list... I'm using VS 2010 with .NetFW 4 Am I missing something? Did you mean that that I should implement the OrderBy with Sort ? – Tal Segal May 30 '12 at 06:57
  • 1
    @TalSegal - Sorry, the full method name is OrderByDescending ( http://msdn.microsoft.com/en-us/library/bb534855 ). You do need to target .NET 3.5 or higher in order to use it. – Polity May 30 '12 at 07:37
  • OK, Found my mistake, OrderByDescending is an extension method in System.Linq, all I was missing is a "using System.Linq" Thank you – Tal Segal May 30 '12 at 09:00
7

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);
jb.
  • 9,921
  • 12
  • 54
  • 90
  • I guess this is the best answer (if you value performance), I did not choose it as the accepted answer because it involved using an additional code component and I stated in the question that performance was less critical. Thank you ! – Tal Segal May 30 '12 at 06:14
  • Nowadays on git: https://morelinq.github.io/ – AnorZaken Oct 07 '21 at 14:47
3

Try that:

var newItem = myList.OrderByDescending(item => item.yourDateTimeField).First();
eyossi
  • 4,230
  • 22
  • 20
  • this might return date only not record – Pranay Rana May 30 '12 at 05:27
  • i changed it a bit and it is fixed – eyossi May 30 '12 at 05:43
  • 1
    It's fairly inefficient to sort the whole list just in order to get a maximum. – JohnB May 30 '12 at 05:45
  • yes...that code same ans me but using exetension method....cheeerss you got 3 upvote for the same answer........ – Pranay Rana May 30 '12 at 05:46
  • @JohnB he wrote "Elegance is more important than efficiency in my case". i didn't say that is an efficient way – eyossi May 30 '12 at 05:48
  • Hm, ok, depends on the definition of "elegant", I suppose. – JohnB May 30 '12 at 05:48
  • 1
    In my humble opinion, sorting when it's unnecessary is the definition of inelegant – jb. May 30 '12 at 06:02
  • Strange, I can not find the any OrderBy method for my Generic list... I'm using VS 2010 with .NetFW 4 Am I missing something? Did you mean that that I should implement the OrderBy with Sort ? – Tal Segal May 30 '12 at 06:58
  • No... it depends which object you work with. i assumed you are working with List which has that extension method. can you specify the list type that you are working with? – eyossi May 30 '12 at 07:06
  • I'm working with System.Collections.Generics.List – Tal Segal May 30 '12 at 07:32
  • In that case all you need is "var newest = myList.Max();" and thats all – eyossi May 30 '12 at 07:33
  • @eyossi - OK, I have Found my mistake, OrderByDescending is an extension method in System.Linq, all I was missing is a "using System.Linq" Thank you – Tal Segal May 30 '12 at 09:02
  • 2
    That was unnecessary, if you will read it you can understand it... myList.OrderByDescending(item => item.yourDateTimeField).First() equals: myList => Order Descending => ByDateTimeField => TakeFirst... what is there to add? how it sorts the list? – eyossi May 30 '12 at 14:56
0

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
)
JohnB
  • 13,315
  • 4
  • 38
  • 65
  • This looks promising but is giving me the following error: `'System.DateTime' does not contain a definition for 'GreaterThan' and no extension method 'GreaterThan' accepting a first argument of type 'System.DateTime' could be found (are you missing a using directive or an assembly reference?)` ... Any suggestions? – Steve Chambers Apr 24 '13 at 16:33
  • Try, e.g., `current > lastOne` instead of `current.GreaterThan (lastOne)`. – JohnB Apr 27 '13 at 08:49
0

try this one

 sortlist.OrderByDescending(a => a.timeStamp).First();
Pravin Pawar
  • 2,559
  • 3
  • 34
  • 40