Your PC can't even




C# - LINQ DistinctBy<T>

This post show how to create a DistictBy extension method for IEnumerable collections.

Why? How is this useful?

  • At times you can end up with a collection that contains multiple entries for a key property. After performing filtering, it can be useful to have an extension method that grabs the first entry based upon a selected key property.

Implementing the method

DistinctBy<T>
		
public static class Extensions
{
        public static IEnumerable<T> DistinctBy<T>(this IEnumerable<T> InObjs, Expression<Func<T, object>> distinctExpr)
     {
           MemberExpression expr = null;
        if (distinctExpr.Body is MemberExpression)
           {
                expr = ((MemberExpression)distinctExpr.Body);
           }
        else
           {
        var op = ((UnaryExpression)distinctExpr.Body).Operand;
                expr = ((MemberExpression)op);
           }
           List<T> OutObjs = new List<T>();
           HashSet<string> ConsumedVals = new HashSet<string>();
        foreach (var element in InObjs)
           {
        object Value = null;
        if (expr.Member is PropertyInfo)
                {
        var _prop = (PropertyInfo)expr.Member;
                      Value = _prop.GetValue(element);
                }
        if (expr.Member is FieldInfo)
                {
        var _field = (FieldInfo)expr.Member;
                      Value = _field.GetValue(element);
                }
        if (Value != null) {
        string sValue = Value.ToString();
        if (!string.IsNullOrEmpty(sValue) && !ConsumedVals.Contains(sValue)) {
                           ConsumedVals.Add(sValue);
                           OutObjs.Add(element);
                      }
                }
        else {
                      OutObjs.Add(element);
                }
           }
        return OutObjs;
     }
}

 
		
		
Usage.
Searching on a collection provided by DBML.
			
//Grab Ecommerce items processed within the last six months, order them by the newest to oldest
var EcommerceItems = EcommercePostingItems.Where(epi => epi.EcommercePostings.ProcessedDate >= DateTime.Now.AddMonths(-6)).ToList().Where(epi => epi.SerialNo != null).OrderByDescending(epi => epi.EcommercePostings.CreatedDate).ToList();

//Get a distinct collection of these items based upon an important SKU and the first serial number we find.
List<EcommercePostingItems> UniquePostings =ConvertedEcoms.Where(x=>!x.SKU.StartsWith("An Important SKU")).OrderByDescending(x =>x.EcommercePostings.CreatedDate ).DistinctBy(x =>x.SerialNo).ToList();