Wednesday, July 26, 2017

Linq – Distinct - fun ?


Linq is nice. Usable. Readable. But … Distinct.
In short. There is no appropriate distinct in Linq.
What I mean “Appropriate” ?. Something like myList.Distinc(x=>x.id).
And there is nothing like that.

Possible solutions:

1. Group by

var queryLastNames =
        from student in students
        group student by student.LastName into newGroup
        orderby newGroup.Key
        select newGroup;

2. Morelinq library

  • it is a Nuget package
  • there is: 
    • myList.DistincBy(x=>x.id)
    • or myList.DistinctBy(x=>new {x.Id1,x.Id2,x.Id3)
  • it is from year 2009 … and it is still not implemented in Linq …
  • Thank you Pranay Rana

3. You can create your own TryToDictionary method


  private static Dictionary<T, K> TryToDictionary<T,K>(
         Func<K,T> getId,
         IEnumerable<K> list)
        {
            var result = new Dictionary<T, K>();
            foreach (var item in list)
            {
                if (result.ContainsKey(getId(item))) continue;
                result.Add(getId(item), item);
            }

            return result;
        }

        private static List<K> TryToUniqueList<T, K>(Func<K, T> getId, IEnumerable<K> list)
        {
            return TryToDictionary<T,K>(getId,list).Select(x => x.Value).ToList();
        }

4. Use original distinct with IEqualityComparer<T>

4.1 Implement IEqualityComparer<T>

.. Just if You really need one ...

4.2 But You can create a lambda version ! :-)

.. thank you Ruben Bartelink and Stackowerflow !

       public class LambdaEqualityComparer<T> : IEqualityComparer<T>
        {
            readonly Func<T, T, bool> _comparer;
            readonly Func<T, int> _hash;

            public LambdaEqualityComparer(Func<T, T, bool> comparer)
                : this(comparer, t => 0)
            {
            }

            public LambdaEqualityComparer(Func<T, T, bool> comparer, Func<T, int> hash)
            {
                _comparer = comparer;
                _hash = hash;
            }

            public bool Equals(T x, T y)
            {
                return _comparer(x, y);
            }

            public int GetHashCode(T obj)
            {
                return _hash(obj);
            }
        }

then you can use it like this

myList.Distinct(new LambdaEqualityComparer<MyClass>((x,y)=>x.Property1.Equals(y.Property1)));


4.2.3 You can  also create it as extension method ...

No comments:

Post a Comment