20

Let's say I have following data:

Name Priority A 3 A 5 B 1 C 1 C 3 C 2 

I want to get list of distinct names with highest priority, so the result would look like:

Name Priority A 5 B 1 C 3 

How can I use Linq to do that?

3 Answers 3

21
var query = yourData .GroupBy(x => x.Name, (k, g) => g.Aggregate((a, x) => (x.Priority > a.Priority) ? x : a)); // and a quick test... foreach (var result in query) { Console.WriteLine(result.Name + " " + result.Priority); } 
Sign up to request clarification or add additional context in comments.

5 Comments

Not sure if you're aware, but LinqPad is great for this kind of quick snippets.
Good idea using with the GroupBy overload that takes a projection. It's just a pity that there's no MaxBy extension method and we have to resort to an aggregate.
@Martinho, we can solve this without aggregate and using max, check my answer....
@Ramesh: you cannot solve it using max if you want to return objects from the input instead of creating new ones.
@Martinho, You are right.. we need to use some projection to get teh source object..
5

Here's an alternative approach:

var items = new List<Tuple<string, int>>() { Tuple.Create("A", 3), Tuple.Create("A", 5), Tuple.Create("B", 1), Tuple.Create("C", 1), Tuple.Create("C", 3), Tuple.Create("C", 2) }; var results = items.GroupBy(i => i.Item1) .SelectMany(g => g .Where(i => i.Item2 == g.Max(m => m.Item2))) .Distinct(); 

Or if you prefer using the C# LINQ syntax:

results = (from item in items group item by item.Item1 into groupedItems let maxPriority = groupedItems.Max(item => item.Item2) from element in groupedItems where element.Item2 == maxPriority select element).Distinct(); 

6 Comments

Just noting that the first version is O(N^2), which is awful for something that can be done in O(N). The second version is not equivalent to the first and runs in O(N). Both produce duplicates if there are any in the input.
@MartinhoFernandes You're absolutely right about the duplicates, I corrected my answer. I can see that the first query is O(N^2), but how did you verify that the second query runs in O(N)? Did you analyze the MSIL?
Sort of. Do you know LinqPad? That's what I use to test these pieces of code. I changed from item in items to from item in items.AsQueryable(), added results.Dump() at the end, and then looked at the "λ" panel below. It shows the query as it was translated from the query expression syntax to the regular lambda syntax. It is easier (at least for me) to evaluate complexity by looking at that. If you want to see the IL, you can, but it looks much better in C# ;)
@Martinho I use LinqPad for all my code samples :) However I never thought of using the "Lambda" panel to evaluate the complexity of LINQ queries that use the C#/VB syntax. I'll certainly do that in the future ;)
Enrico, I am trying to use your linq (the second example in LINQ syntax.) However I am getting duplicates. Do you know how I would eliminate duplicates?
|
2

Another simple approach without aggregating

 var listNP = new List<NP>() { new NP() {name="A",priority=3}, new NP() {name="A",priority=5}, new NP() {name="b",priority=1}, new NP() {name="b",priority=1}, new NP() {name="c",priority=3}, new NP() {name="c",priority=2}, }; var np = listNP.GroupBy(x => x.name).Select(y => new { name = y.Key, max = y.Max(x=>x.priority) }).ToList(); 

Update:

var np = listNP.GroupBy(x => x.name) .Select(y => y.OrderByDescending(z => z.priority).First()).ToList(); 

4 Comments

I know the question doesn't make it explicit, but note that this solution produces data of a type different from the source.
@Martinho, you are rightt. still we can fix it by OrderByDescending without aggregate......
that works, but note that it raises execution time from O(N) to O(N log N).
@Martinho, yep we need to consider that too :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.