2

I have 2 classes like this:

public partial class Product
{
    public ICollection<ProductTerm> ProductTerms { get; set; }
    // More properties here
}

public partial class ProductTerm
{
    public short ID { get; set; }
    public short MinTermDuration { get; set; }
    // More properties here
}

As you will see, Product has a 1 to many relationship with ProductTerm.

I'm trying to return the entire ProductTerm with the Min MinTermDuration. I can get the result I want here but am returning the MinTermDuration - how do I return the whole ProductTerm?

    int GetMinTerm()
    {
        return ProductTerms.Min(t => t.MinTermDuration);
    } 
1
  • 1
    See here Commented Dec 18, 2014 at 9:52

3 Answers 3

8

You can first order your products and then just take the first one on the top.

return ProductTerms.OrderBy(t => t.MinTermDuration).FirstOrDefault();
Sign up to request clarification or add additional context in comments.

Comments

3

You could use OrderBy(...).FirstOrDefault(), as suggested by Vsevolod Goloviznin; however this approach needs to sort the collection, which has a complexity of O(n log n)... The approach suggested by Selman22 is better, but it still enumerates the result twice (which could be an issue if the sequence is an Entity Framework or OData query).

A better option is to use a MinBy extension method that just loops over the collection once and returns the item that has the min value, with a complexity of O(n):

return ProductTerms.MinBy(t => t.MinTermDuration);

You can find such a method in Linq.Extras or in MoreLinq.


EDIT: the above is true if you're working with an in-memory collection (Linq to Objects), not if you're working with a database (using Entity Framework for instance). The DB knows how to find the item with the min value efficiently; using MinBy in this case would fetch all rows to examine them, so it would be very inefficient.

3 Comments

I am using Entity Framework - what would the issue be?
@dotnetnoob, EF queries implement IEnumerable<T>, so it should work fine. However, in this case it's better to use the OrderBy approach, because the DB can do it efficiently, whereas using MinBy would fetch all rows to examine them...
Ah, I see. This shouldn't be a problem - there are less than 100 products, each with around 5 terms. The data is retrieved .AsNoTracking and cached prior to any property being requested.
1

Min returns the minimum value, not the item with the value. You can use First to get ProductTerm that has MinTermDuration:

ProductTerm GetMinTerm()
{
    var min = ProductTerms.Min(t => t.MinTermDuration);
    return ProductTerms.First(x => x.MinTermDuration == min);
} 

Another alternative would be using MinBy method, it requires using a thir-party library but more straightforward:

ProductTerm GetMinTerm()
{
    return ProductTerms.MinBy(t => t.MinTermDuration);
} 

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.