0

My data looks like the following imageenter image description here

So i loaded it into a collection, using anon objects to bypass creating a class

List<dynamic> myList = new List<dynamic>()
        {
            new {
                WorkOrderID = 40001,
                LastUpdatedAt = DateTime.Parse("2018-10-02"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40001,
                LastUpdatedAt = DateTime.Parse("2017-06-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40002,
                LastUpdatedAt = DateTime.Parse("2018-07-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40003,
                LastUpdatedAt = DateTime.Parse("2018-09-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40001,
                LastUpdatedAt = DateTime.Parse("2016-01-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40002,
                LastUpdatedAt = DateTime.Parse("2016-12-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
        };

How do I use Linq-to-Objects to extract only DISTINCT WorkOrders that were updated most recently.

In other words, i should end up with the 3 rows highlighted in Orange.

var myFilteredList = myList.GroupBy( //?? Totally lost... help...

1
  • It would be awesome if you could be explicit about the results you are expecting. Commented Oct 16, 2018 at 2:44

3 Answers 3

2

If I'm not misunderstanding, you want the newest item per work order.

var latestWorkOrders = myList
    .GroupBy(w => w.WorkOrderID)
    .Select(g => g.OrderByDescending(w => w.LastUpdatedAt).First());

It will group by the WorkOrderID, and for each grouping select the newest item.

Sign up to request clarification or add additional context in comments.

2 Comments

is your left hand side latestWorkOrders a LINQ query, rather than final result? i.e. i still need to do var finalList = latestWorkOrders.ToList()
Sorry, yes. It's a LINQ query, so you will need .ToList().
2

The following uses the GroupBy overload so the element selection can be done in the same call and convert them to strongly typed anonymous object.

var myFilteredList = myList
    .GroupBy(_ => (int)_.WorkOrderID, (k, g) =>
    {
        var recent = g.OrderByDescending(_ => _.LastUpdatedAt).First();
        return new
        {
            WorkOrderID = k,
            LastUpdatedAt = (DateTime)recent.LastUpdatedAt,
            Col3 = (string)recent.Col3,
            Col4 = (string)recent.Col4
        };
    });

Fiddle

1 Comment

Thanks for your answer, It does work but i went with the first correct reply; Your left hand side is a linq query, rather than the final list, missing a .ToList() cast at the end ?
0
List<dynamic> list = myList
               .GroupBy(a => a.WorkOrderID )
               .OrderByDescending(b => b.LastUpdatedAt)
               .Select(g => g.FirstOrDefault())
               .ToList();

foreach (var p in list)
{
    Console.WriteLine(p.WorkOrderID + " : " + p.Col3);
}

Personally, dynamic isnt a good choice. If you have an object, then you can implement Equals and GetHashCode on the Object. This way you can do:

var list = myList.Select(o => new { o.WorkOrderID, ... })
                                       .Distinct();

which is much cleaner.

1 Comment

IGrouping<dynamic, dynamic> does not contain a definition for LastUpdatedAt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.