So you have a sequence of similar items, where every item has at least a property Key
which is of a type that implements IComparable.
You want from all items in your sequence the item that has the lowest value for property Key
. If there are several with the same lowest value, you don't care which one you get.
If you write it like this, the solution is simple:
var result = myKeyValuePairs.OrderBy(keyValuePair => keyValuePair.Key).FirstOrDefault();
In words: take your original sequence of keyValuePairs. Order this sequence in ascending order by value of keyValuePair.Key, from the resulting sequence take the first one, or return null if the sequence is empty.
Although this works, and although this looks very easy to understand, it is not very efficient to order the 2nd smallest, 3rd smallest, etc, if you only need the smallest one.
A more efficient method would be to use Enumerable.Aggregate. Careful though, this function only works if you are certain that there is at least one element in your sequence. If not, you should first assert that the sequence is not empty.
if (myKeyValuePairs.Any())
return myKeyValuePairs.Aggregate( (lowestPair, currentPair) =>
(lowestPair.Key <= currentPair.Key) ? lowestPair : currentPair);
else
return null;
However, because of Any(), you'll enumerate the first element twice. Besides every loop you'll do an assignment.
An even more optimized code, where you enumerate the sequence exactly once, would be an extension function like:
TSource SmallestOrDefault<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, Tkey> keySelector)
{
// TODO: check null source or keySelector
IEnumerator<TSource> enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
{
// sequence not empty. The first element is smallest until now
TSource smallestElement = enumerator.Current;
// check the rest of the sequence to see if there are smaller elements
while (enumerator.MoveNext)
{
// there is a next element. Is it smaller?
if (enumerator.Current < smallestElement)
{
// found a new smallest element
smallestElement = enumerator.Current;
}
}
return smallestElement;
}
else
// empty sequence
return null;
}
Usage:
var smallestElement = myKeyValuePairs.SmallestOrDefault(
keyValuePair => keyValuePair.Key);