-1

If I want to get the min type of a collection, applying some criteria of the class values for a complex class with a lot of variables and fields, that cannot be done directly.

The closest attempt is:

public static TSource Min<TSource>(this IEnumerable<TSource> source);

For a simple class its clear:

public static void MaxEx3()
{
    Pet[] pets = { new Pet { Name="Barley", Age=8 },
                   new Pet { Name="Boots", Age=4 },
                   new Pet { Name="Whiskers", Age=1 } };

    Pet max = pets.Max();

    Console.WriteLine(
        "The 'maximum' animal is {0}.",
        max.Name);
}

/*
 This code produces the following output:

 The 'maximum' animal is Barley.
*/

But for a type with many fields there is no implementation such as: "return this specific type where the value of a determined fiel is minimal". For example from a Vector3 collection the one with the minimum z.

Closest workaround would be returning a collection of your type like this (for a Vector3 type):

OrderBy( vector => vector.z).Take(1).ToList();

I found this quite curious, as I find the source type return with a criteria in determined class field type or with any other predicate appliying logic the check of the class values themselves quite handy. Is there any explanation for this?

rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47
  • 3
    MoreLinq has `MinBy`. But the `OrderBy` solution works for most scenarios (including IQueryables) - so there is no real need for an "inbuilt" MinBy. – mjwills Jan 19 '21 at 09:12
  • whats MoreLinq? – rustyBucketBay Jan 19 '21 at 09:13
  • no need of. With orderby you can make it, but seems quite a handy implementation not to have by default. At least for me – rustyBucketBay Jan 19 '21 at 09:15
  • 1
    Lots of things are handy. Adding something that is easily composed from other things can result in hiding more useful features. It is a tough balance. – mjwills Jan 19 '21 at 09:17
  • `Select( vector => vector.z ).Min()` returns the min float, not the vector. My point is that I would like to have the vector with min z returned, by this I mean the vector type instance. Thanks – rustyBucketBay Jan 19 '21 at 09:35
  • 3
    @rustyBucketBay Did you try `MinBy`? – mjwills Jan 19 '21 at 09:38
  • 1
    `OrderBy( vector => vector.z).FirstOrDefault()` would return the first item of type `Vector3` from the order ordered collection. – Chetan Jan 19 '21 at 09:41
  • 2
    https://stackoverflow.com/questions/3188693/how-can-i-get-linq-to-return-the-object-which-has-the-max-value-for-a-given-prop – Chetan Jan 19 '21 at 09:43
  • @mjwills my intention is not to incorporate external libraries to my project. Checking the code it seems to do the work. Thanks – rustyBucketBay Jan 19 '21 at 09:48
  • This example with `Pet` class is not clear to me. C# can't just pick a field out of thin air to compare classes. Pet has to implement `IComparable` for this to work. – Dialecticus Jan 19 '21 at 10:23
  • 1
    `MinBy` is definitely what you want. – Aluan Haddad Jan 19 '21 at 10:39
  • 1
    `my intention is not to incorporate external libraries to my project. Checking the code it seems to do the work.` Copy the source code from MoreLinq then. I mean, I think your intention is foolish (and inconsistent - since you are clearly already using libraries), but the code is easy to copy and paste if you want to. – mjwills Jan 19 '21 at 10:53
  • 2
    `C# can't just pick a field out of thin air to compare classes.` It isn't picking a field out of thin air - the OP wants it to choose based on the `z` value. Which `MinBy` does just fine. – mjwills Jan 19 '21 at 10:54

1 Answers1

1

There is one Enumerable.Min implementations in LINQ that returns TSource. It requires that the class implements IComparable<T> (in your case IComparable<Pet>) or older plain IComparable. In the method CompareTo you have to provide the code that can be used to determine the relation between any two instances of the class. This method has to provide "stable" results.

Dialecticus
  • 16,400
  • 7
  • 43
  • 103