Feedback

linq DistinctBy for IEnumerable

Sprache: C#

Das snippet erlaubt ein DistinctBy mit propertySelector um die gewünschte property die eindeutig sein muss auszuwählen. Die implementierung benötigt c# 6! Durch das nutzen des selben namespaces wie die .NET Linq methoden ist diese Methode immer verfügbar wenn System.Linq eingebunden ist. Usage: [code]var distinctByNames = items.Distinct(x => x.Name);[/code]
namespace System.Linq;
{
    using System;
    using System.Collections.Generic;

    public static class EnumerableExtensions
    {
        public static IEnumerable<TSource> Distinct<TSource, TProperty>(this IEnumerable<TSource> target, Func<TSource, TProperty> propertySelector)
        {
            return target.Distinct(propertySelector, EqualityComparer<TProperty>.Default);
        }

        public static IEnumerable<TSource> Distinct<TSource, TProperty>(this IEnumerable<TSource> target, Func<TSource, TProperty> propertySelector,
            IEqualityComparer<TProperty> propertyEqualityComparer)
        {
            return target.Distinct(new PropertyComparer<TSource, TProperty>(propertySelector, propertyEqualityComparer));
        }

        private class PropertyComparer<TElement, TProperty> : IEqualityComparer<TElement>
        {
            private readonly Func<TElement, TProperty> propertySelector;
            private readonly IEqualityComparer<TProperty> propertyComparer;

            public PropertyComparer(Func<TElement, TProperty> propertySelector)
            {
                this.propertySelector = propertySelector;
            }

            public PropertyComparer(Func<TElement, TProperty> propertySelector, IEqualityComparer<TProperty> propertyComparer)
            {
                this.propertySelector = propertySelector;
                this.propertyComparer = propertyComparer;
            }

            public bool Equals(TElement x, TElement y)
            {
                return this.propertyComparer?.Equals(this.propertySelector(x), this.propertySelector(y)) ?? this.propertySelector(x).Equals(this.propertySelector(y));
            }

            public int GetHashCode(TElement obj)
            {
                return this.propertyComparer?.GetHashCode(this.propertySelector(obj)) ?? this.propertySelector(obj).GetHashCode();
            }
        }
    }
}
namespace System.Linq;
{
    using System;
    using System.Collections.Generic;

    public static class EnumerableExtensions
    {
        public static IEnumerable<TSource> Distinct<TSource, TProperty>(this IEnumerable<TSource> target, Func<TSource, TProperty> propertySelector)
        {
            return target.Distinct(propertySelector, EqualityComparer<TProperty>.Default);
        }

        public static IEnumerable<TSource> Distinct<TSource, TProperty>(this IEnumerable<TSource> target, Func<TSource, TProperty> propertySelector,
            IEqualityComparer<TProperty> propertyEqualityComparer)
        {
            return target.Distinct(new PropertyComparer<TSource, TProperty>(propertySelector, propertyEqualityComparer));
        }

        private class PropertyComparer<TElement, TProperty> : IEqualityComparer<TElement>
        {
            private readonly Func<TElement, TProperty> propertySelector;
            private readonly IEqualityComparer<TProperty> propertyComparer;

            public PropertyComparer(Func<TElement, TProperty> propertySelector)
            {
                this.propertySelector = propertySelector;
            }

            public PropertyComparer(Func<TElement, TProperty> propertySelector, IEqualityComparer<TProperty> propertyComparer)
            {
                this.propertySelector = propertySelector;
                this.propertyComparer = propertyComparer;
            }

            public bool Equals(TElement x, TElement y)
            {
                return this.propertyComparer?.Equals(this.propertySelector(x), this.propertySelector(y)) ?? this.propertySelector(x).Equals(this.propertySelector(y));
            }

            public int GetHashCode(TElement obj)
            {
                return this.propertyComparer?.GetHashCode(this.propertySelector(obj)) ?? this.propertySelector(obj).GetHashCode();
            }
        }
    }
}

3 Kommentare

  1. Warum DistinctBy und nicht Distinct? Letzteres würde einen direkten Bezug zu den bereits existierenden Methoden darstellen, nur dass du eben einen Delegaten statt einem IEqualityComparer entgegen nimmst.