0

Consider the following class hierarchy:

public class Foo
{
 public string Name { get; set; }
 public int Value { get; set; }
}
public class Bar
{
 public string Name { get; set; }
 public IEnumerable<Foo> TheFoo { get; set; }
}

public class Host
{
  public void Go()
  {
    IEnumerable<Bar> allBar = //Build up some large list
    //Get Dictionary<Bar, Foo> with max foo value
  }
}

What I would like to do using Linq2Objects is to get an KeyValuePair where for each Bar in the allBBar collection we select the Foo with the maximum Value property. Can this be done easily in a single LINQ statement?

3 Answers 3

2

Sure, although my preferred solution uses MaxBy from MoreLINQ:

var query = allBar.ToDictionary(x => x, // Key
                                x => x.TheFoo.MaxBy(f => f.Value));

Note that this will go pear-shaped if TheFoo is empty for any Bar instance.

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

2 Comments

And without the MaxBy option?
Then you'd basically want to write your own implementation of MaxBy :) You could do something horrible, but it would be a lot neater just to include MaxBy in your code.
1

Another way using Aggregate instead of OrderBy so that figuring out the max Foo is O(n) instead of O(n log n):

var query = allBar.ToDictionary(
    bar => bar,
    bar => bar.TheFoo.Aggregate(
        null,
        (max, foo) => (max == null || foo.Value > max.Value) ? foo : max));

Comments

0

just to add to Jon's comment about MaxBy going pear shaped if you have no foos, you could do an OrderByDescending and then use FirstOrDefault to get at the Max element. If the collection is empty it'd just return null instead of going "pear shaped".

var foobars = bars.ToDictionary(bar => bar, 
                                bar => bar.TheFoo.OrderByDescending(foo => foo.Value).FirstOrDefault());

I don't think this wouldn't be as efficient as MaxBy, but it'd be more robust in the case of an empty collection.

Comments

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.