views:

975

answers:

5
+2  Q: 

Select max age C#

Greetings,

I created a list that contains a collection of objects that have this properties: X, Y, Z

I want to find out which object in the collection has the greatest Z

I tried to use the Max() function but I don't understand how it's used...

How can I accomplish this

Thanks in advance

+2  A: 
int maxAge = myList.Max(obj => obj.Z);

The parameter used is a lambda expression. This expression indicates which property to use(in this case, Z) to get the max value. This will get the maximum age. If you want the object which has the greatest age, you could sort by age and get the first result:

MyType maxItem = myList.OrderByDescending(obj => obj.Z).First();

If you do it this way, note that if two or more items all have the maximum age, only one of them is selected.

Meta-Knight
That gets the maxAge but it doesn't tell you which object has that maxAge
AnthonyWJones
but this will return the X value right???I would like to retrieve the object with the highest X
Killercode
Note that you will need to use the directive "using System.Linq;" at the top of your file.
Paul Williams
You're right. I'll edit.
Meta-Knight
A: 

It will largely depend on the type of X, if it is comparable:

var array = new[] { 
    new { X = "a", Y = "a", Z = 1 }, 
    new { X = "b", Y = "b", Z = 2 } 
};
var max = array.Max(x => x.Z);
Console.WriteLine(max);
Darin Dimitrov
+5  A: 

Max is used to find the maximum value of a property. Once you have the maximum value you can select those objects whose value matches using the Where clause.

var maxZ = list.Max( obj => obj.Z );
var maxObj = list.Where( obj => obj.Z == maxZ );
tvanfosson
Note that this does two passes over the list and may return multiple objects. These attributes may or may not be a concern for your own application.
Brian
If list.Count is large, that isn't exactly that performant.
sixlettervariables
+1 for your answer from me though I don't like the lower case L (which I understand is for list but looks frightenly like one of my favorite numbers).
Jay Riggs
I agree this isn't necessarily the fastest, but it's pretty clean and unless the list is very large, it should be pretty fast. It will -- by design -- return multiple matches. If you only want the first one, change the Where() to FirstOrDefault().
tvanfosson
@Jay -- updated the lambda variable, just for you.
tvanfosson
I agree that this is the cleanest way to do this using built-in functions.
Meta-Knight
+3  A: 

To get the object with the greatest Z value you sort on the Z value in descending order and get the first item:

TypeOfObject oldest = list.OrderByDescending(x => x.Z).First();

Edit:
Changed it to use the IEnumerable.OrderByDescending method instead of List.Sort.

Edit 2:
If you want performance, this is about four times faster than the fastest LINQ solution:

int high = Int32.MinValue;
List<TypeOfObject> highest = new List<TypeOfObject>();
foreach (TypeOfObject v in list) {
   if (v.Z >= high) {
      if (v.Z > high) highest.Clear();
      high = v.Z;
      highest.Add(v);
   }
}
Guffa
+1, optionally: list.OrderByDescending(x => x.Z).First()
sixlettervariables
A couple of issues here. First, sorting is at best O(nlogn), where as finding the maximum and extracting matching elements are both O(n). Second, this only gives you the first match. That's ok if the values are unique or you only care about getting any matching element, but if you need them all, you'll still have to find the maximum and then extract the matches.
tvanfosson
@sixlettervariables: Yes, I knew that it was there somewhere, but it doesn't show up in the 'List<T>' documentation, so I had to dig a bit...
Guffa
@tvanfosson: Yes, but on the other hand you don't have to enumerate the entire collection twice. If more than one item can have the largest value, you have them all at the beginning of the result, so they are easy to get.
Guffa
@Guffa for n > 4, 2*n < nlogn.
tvanfosson
A: 

If can implement either IComparable<T> or IComparable on your class along these lines:

public Int32 CompareTo(MyClass other) {
  return Z.CompareTo(other.Z);
}

You can get the maximum value simply by calling (this will require using System.Linq):

MyClass maxObject = list.Max();

This will only perform a single pass over your list of values.

Martin Liversage