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();
}
}
}
}
Alte URL:
/snippet/linq-distinctby-for-ienumerable/10011
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.
@Koopakiller Stimmt könnte man noch anpassen, die Unterscheidung sollte eigentlich nicht nötig sein.
Dann passe es an 😉
Über dem Snippet ist ein Link zum bearbeiten des Snippets (nur für dich sichtbar)