How to use LINQ Distinct() with multiple fields

前端 未结 9 1371
借酒劲吻你
借酒劲吻你 2020-11-30 01:32

I have the following EF class derived from a database (simplified)

class Product
{ 
     public string ProductId;
     public string Product         


        
9条回答
  •  悲哀的现实
    2020-11-30 01:59

    Answering the headline of the question (what attracted people here) and ignoring that the example used anonymous types....

    This solution will also work for non-anonymous types. It should not be needed for anonymous types.

    Helper class:

    /// 
    /// Allow IEqualityComparer to be configured within a lambda expression.
    /// From https://stackoverflow.com/questions/98033/wrap-a-delegate-in-an-iequalitycomparer
    /// 
    /// 
    public class LambdaEqualityComparer : IEqualityComparer
    {
        readonly Func _comparer;
        readonly Func _hash;
    
        /// 
        /// Simplest constructor, provide a conversion to string for type T to use as a comparison key (GetHashCode() and Equals().
        /// https://stackoverflow.com/questions/98033/wrap-a-delegate-in-an-iequalitycomparer, user "orip"
        /// 
        /// 
        public LambdaEqualityComparer(Func toString)
            : this((t1, t2) => toString(t1) == toString(t2), t => toString(t).GetHashCode())
        {
        }
    
        /// 
        /// Constructor.  Assumes T.GetHashCode() is accurate.
        /// 
        /// 
        public LambdaEqualityComparer(Func comparer)
            : this(comparer, t => t.GetHashCode())
        {
        }
    
        /// 
        /// Constructor, provide a equality comparer and a hash.
        /// 
        /// 
        /// 
        public LambdaEqualityComparer(Func comparer, Func hash)
        {
            _comparer = comparer;
            _hash = hash;
        }
    
        public bool Equals(T x, T y)
        {
            return _comparer(x, y);
        }
    
        public int GetHashCode(T obj)
        {
            return _hash(obj);
        }    
    }
    

    Simplest usage:

    List products = duplicatedProducts.Distinct(
        new LambdaEqualityComparer(p =>
            String.Format("{0}{1}{2}{3}",
                p.ProductId,
                p.ProductName,
                p.CategoryId,
                p.CategoryName))
            ).ToList();
    

    The simplest (but not that efficient) usage is to map to a string representation so that custom hashing is avoided. Equal strings already have equal hash codes.

    Reference:
    Wrap a delegate in an IEqualityComparer

提交回复
热议问题