Find Max / Min Element Without Using IComparable <T>
Say I have the following:
public Class BooClass
{
public int field1;
public double field2;
public DateTime field3;
}
public List<BooClass> booList;
So, for example, how to get the element with the earliest time in field3 using booList.Find ()
Modify my apologies, I wanted to make all fields public for the sake of simplicity. I know that I can do this in linq, I wondered if there is one simple condition for the Find method.
F # has convenient operators minByand maxBywhich I like to implement as C # extension methods, since the Linq library skips them. This is a little work, but only a little, and this avoids complex expressions such as
var earliest = booList.First(b => b.Field3 == booList.Min(e => e.Field3));
Instead, you can enter the following:
var earliest = booList.MinBy(b => b.Field3);
Simple implementation:
static T MinBy<T, C>(this IEnumerable<T> sequence, Func<T, C> keySelector)
{
bool first = true;
T result = default(T);
C minKey = default(C);
IComparer<C> comparer = Comparer<C>.Default; //or you can pass this in as a parameter
foreach (var item in sequence)
{
if (first)
{
result = item;
minKey = keySelector.Invoke(item);
first = false;
continue;
}
C key = keySelector.Invoke(item);
if (comparer.Compare(key, minKey) < 0)
{
result = item;
minKey = key;
}
}
return result;
}
, , MinBy , . , , , , O (n log n), O (n).
3 ( Field3), :
var earliest = booList.First(b => b.Field3 == booList.Min(e => e.Field3));
, BooClass , List<T>.Find. , :
void Main()
{
List<BooClass> booList = new List<BooClass> {
new BooClass { field3 = DateTime.MaxValue},
new BooClass { field3 = DateTime.Now },
new BooClass { field3 = DateTime.MinValue }};
var pred = GetPredicate(booList);
var result = booList.Find(pred);
}
public Predicate<BooClass> GetPredicate(List<BooClass> boos)
{
var minDate = boos.Min(boo => boo.field3);
return bc => bc.field3 == minDate;
}
(which, like Said’s solution, also has O (n) time complexity), but I assume that would be considered a hoax ...