Jump to content
  • Advertisement
Sign in to follow this  

[.net] LINQ to Objects (.Min)

This topic is 3718 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been using the recent C# and .NET stuff pretty heavily in a project for work. In particular, I've been using the LINQ and new lambda syntax quite a bit. I like it, because if I'm just selecting some subset of elements or doing any kind of query, I can almost always get away without temporary variables or a foreach loop. But today I hit a (minor) snag. I have a collection of things. I want to find the thing with the minimum timestamp. Previously, the surrounding code didn't need to know the object itself, so I was just doing this:
DateTime oldestTime = Collection.Min(obj=>obj.Timestamp);

Now I need to get the object itself. Obviously, I can easily write a foreach loop to find the oldest object. Or I could write a new extension method for IEnumerable and IQueryable to add to the huge set of operations provided by LINQ. But before I do that... am I missing some really obvious way to do this with the existing operations? Min always returns the value of the thing being compared. The only way I can see to implement this using the existing functions would be:
MyObject oldestObject = Collection.OrderBy(obj => obj.Timestamp).First();

This does what I want, but forces me to pay the price of an unnecessary sort on the collection. Before anyone asks, keeping the collection sorted by Timestamp isn't really an option ... it's queried in lots of different ways so I wouldn't really be solving anything by doing that. So, is there some other function that I've overlooked that would do what I want without the extra cost of sorting?

Share this post

Link to post
Share on other sites
You can use the Aggregate operator:

class Person
public string Name;
public int Age;

var people = new[]
new Person { Name = "Bob", Age = 5 },
new Person { Name = "Joanne", Age = 19 },
new Person { Name = "Walter", Age = 25 },
new Person { Name = "Mary", Age = 1 },
new Person { Name = "Karen", Age = 13 },
new Person { Name = "Patricia", Age = 79 },
new Person { Name = "Billy", Age = 43 },

var youngestPerson = people.Aggregate((person, nextPerson) => person.Age < nextPerson.Age ? person : nextPerson);
Console.WriteLine(youngestPerson.Name); // Prints Mary

The above is a bit more unweildy than Min, but you repackage it as an extension method.

public static TObject MinObject<TObject, TValue>(this IEnumerable<TObject> source, Func<TObject, TValue> selector)
var comparer = Comparer<TValue>.Default;
var minObject = source.Aggregate(
(obj, nextObject) =>
(comparer.Compare(selector(obj), selector(nextObject)) < 0) ? obj : nextObject
return minObject;

youngestPerson = people.MinObject(person => person.Age);

Share this post

Link to post
Share on other sites
Ooh. Thanks. Yeah, I hadn't use Aggregate yet, so I wasn't familiar with the semantics. That looks perfect. I had already gone and written my own extension methods, but they're far more unwieldy than your version. rate++.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!