0

I have a List of Presidents:

var obj = new List<President>();

They have fields Name and BeginningGovernance. The Name can be repeated in list. The BeginningGovernance cann't repeat. I need take List of unique by Name Presidents with the oldest BeginningGovernance (if name repeated).

How can I do this with help of Linq?

2 Answers2

2

Try GroupBy:

  1. Group by Name
  2. Pick up the right president among ones with the same Name
  3. Materialize to List "I need take list..."

Implementation:

var result = obj
  .GroupBy(president => president.Name)
  .Select(chunk => chunk // among presidents who have the same name
     .OrderBy(president => president.BeginningGovernance)
     .First())
  .ToList();  
Dmitry Bychenko
  • 149,892
  • 16
  • 136
  • 186
  • Great! But I need use **OrderBy** that to take him first time of governance (the oldest) – Mikhail Tarasov Oct 27 '17 at 13:31
  • @Михаил Тарасов: `OrderByDescending` sort the presidents in reversed order (the oldest will be the first) – Dmitry Bychenko Oct 27 '17 at 13:51
  • `(...).ToList()` – Mr Anderson Oct 27 '17 at 14:24
  • @DmitryBychenko, I'm ask about his **first time** of governance. The last date is the one that is closer to the present time (we need OrderByDescending sort the presidents in reversed order). But the **first time** - the **oldest date** (we need sort OrderBy to take First). My english is not very good. It may be difficulties of translation. – Mikhail Tarasov Oct 27 '17 at 17:18
  • I see, I am sorry for my misunderstanding, it should be `OrderBy` then – Dmitry Bychenko Oct 27 '17 at 18:09
  • The OrderBy in this case is likely to be cheap, since the list of collisions is going to be very short. But in cases where the list of collisions is very long, you're doing a lot of work to sort a list in order to take only the smallest element. A more efficient query would use this https://stackoverflow.com/questions/914109/how-to-use-linq-to-select-object-with-minimum-or-maximum-property-value and then you get `obj.GroupBy(p => p.Name).Select(g => g.MinBy(p => p.BeginningGovernance)).ToList()` which is both more efficient in the asymptotic case, and easier to understand. – Eric Lippert Oct 27 '17 at 19:02
0

The accepted answer is fine. I'll just point out that you could write a query that is shorter and easier to understand by using this code:

https://github.com/morelinq/MoreLINQ/blob/8fbb540fd140b6d0008120c37abd00e129203cc6/MoreLinq/DistinctBy.cs

Your query would then be

presidents
  .OrderBy(p => p.BeginningGovernance)
  .DistinctBy(p => p.Name)
  .ToList()

which is extremely easy to read and understand.

Exercise: Suppose we swapped the order of the OrderBy and DistinctBy; would the query still be correct? Why or why not?

Eric Lippert
  • 612,321
  • 166
  • 1,175
  • 2,033