Another alternative, which only needs a single pass through the rows:
int rptGroup = dt.AsEnumerable()
.Where(row => row.Field<int>("BandingStart") == 1000 && row.Field<int>("BandingEnd") == 2000)
.OrderByDescending(row => row.Field<int>("Weighting"))
.Select(row => row.Field<int>("RPTGroup"))
.FirstOrDefault();
Unfortunately, the
OrderBy
operator has to store every item from the source sequence in a list, since it doesn't know the final order until it has completely enumerated the source.
If you're open to using custom extension methods:
public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> keyComparer = null)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
if (keyComparer == null) keyComparer = Comparer<TKey>.Default;
bool isEmpty = true;
TSource current = default(TSource);
bool canBeNull = current != null;
if (canBeNull) source = source.Where(x => x != null);
foreach (var value in source)
{
if (isEmpty)
{
current = value;
isEmpty = false;
}
else if (keyComparer.Compare(keySelector(value), keySelector(current)) > 0)
{
current = value;
}
}
if (!isEmpty || canBeNull) return current;
throw new InvalidOperationException(string.Format("Cannot calculate an aggregate for an empty sequence of the non-nullable value type '{0}'.", typeof(TSource)));
}
Your code would then become:
DataRow maxRow = dt.AsEnumerable()
.Where(row => row.Field<int>("BandingStart") == 1000 && row.Field<int>("BandingEnd") == 2000)
.MaxBy(row => row.Field<int>("Weighting"));
int rptGroup = maxRow?.Field<int>("RPTGroup") ?? 0;