问题描述
我需要在 Union 上实现比较对象的属性,而不是对象本身.我想出了以下几点:
public static IEnumerable<TSource> UnionBy<TSource, TKey>( this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null) { HashSet<TKey> keys = new HashSet<TKey>(keyComparer); foreach (TSource element in first) { if (keys.Add(keySelector(element))) { yield return element; } } foreach (TSource element in second) { if (!keys.Add(keySelector(element))) { continue; } yield return element; } }
我可以这样说:
result = first.UnionBy(second, x => x.Property1);
这对我有用,但我想知道在 Linq 中是否已经实现了一些我缺少的东西(除了实现我自己的 EqualityComparer,这对我来说似乎不太直观).
因为每次我想要这个联合时我都不会使用相同的属性,所以我要么必须为每种我认为不正确的情况制作多个 EqualityComparer,要么制作一些通用的 EqualityComparer这将包含一个属性选择器 Func.对我来说,这似乎不如提供一个接受属性选择器本身的通用 Linq 扩展那么直观.
推荐答案
是的,你可以改为:
var q = first.Concat(second).GroupBy(x => x.Property1).Select(x => x.First());
问题描述
I needed an implementation on Union that compares a property of an object, rather the objects themselves. I came up with the following:
public static IEnumerable<TSource> UnionBy<TSource, TKey>( this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null) { HashSet<TKey> keys = new HashSet<TKey>(keyComparer); foreach (TSource element in first) { if (keys.Add(keySelector(element))) { yield return element; } } foreach (TSource element in second) { if (!keys.Add(keySelector(element))) { continue; } yield return element; } }
which I can use by saying something along the lines of:
result = first.UnionBy(second, x => x.Property1);
Which works for me, but I was wondering if there wasn't something already implemented in Linq that I was missing (other than implementing my own EqualityComparer which to me seems less intuitive).
Since I won't be using the same properties every time I want this union I would either have to make multiple EqualityComparer's for each situation which doesn't seem correct to me, or make some generic EqualityComparer that would take in a property selector Func. It seemed less intuitive to me than just providing a generic Linq extension that accepted the property selector itself.
推荐答案
Yes you can write it as follows instead:
var q = first.Concat(second).GroupBy(x => x.Property1).Select(x => x.First());