I used a Select() to perform a calculation on each member of an array of structs and now want to have the member for which a certain attribute is minimal. I wanted to use something like Min() on the selected sequence, but I don't know how to return the full struct, rather than only the attribute that is minmal.
From stackoverflow
-
If i understand correctly, i'd say: use delegates...
Here's an Example from Craig Murphy
public class Person { public int age; public string name; public Person(int age, string name) { this.age = age; this.name = name; } } // everyone under 25: List<person> young = people.FindAll(delegate(Person p) { return p.age < 25; }); // sort your list: people.Sort(delegate(Person p1, Person p2) { return p1.age.CompareTo(p2.age); });
-
Sounds like you want to use
MinBy
from MoreLINQ:public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IComparer<TKey> comparer) { source.ThrowIfNull("source"); selector.ThrowIfNull("selector"); comparer.ThrowIfNull("comparer"); using (IEnumerator<TSource> sourceIterator = source.GetEnumerator()) { if (!sourceIterator.MoveNext()) { throw new InvalidOperationException("Sequence was empty"); } TSource min = sourceIterator.Current; TKey minKey = selector(min); while (sourceIterator.MoveNext()) { TSource candidate = sourceIterator.Current; TKey candidateProjected = selector(candidate); if (comparer.Compare(candidateProjected, minKey) < 0) { min = candidate; minKey = candidateProjected; } } return min; } }
ThrowIfNull
is defined as an extension method:internal static void ThrowIfNull<T>(this T argument, string name) where T : class { if (argument == null) { throw new ArgumentNullException(name); } }
Hosam Aly : How is this different from `source.OrderBy(selector, comparer).FirstOrDefault()`?configurator : Efficiency. OrderBy is O(n * lg n), this is O(n) I believe.Hosam Aly : You're right @configurator. I have just taken a look at the implementation of OrderBy, and I agree. +1 Jon. -
How about ordering by your "value" and taking the first entry (the minimum value):
Persons.OrderBy(p => p.Age).FirstOrDefault();
That is of course if you only want one item (which is what you state).
Alternatively:
from p in Persons where p.Age == Persons.Select(p1 => p1.Age).Min() select p;
Will get you all items with minimum value.
Hosam Aly : +1. I would have done it in the same way (at least for one item).Hosam Aly : Jon's answer has better performance, but this one is more "built-in".
0 comments:
Post a Comment