我讨厌发布它,因为它有些主观,但是感觉有一种更好的方法,我只是没有想到。
有时,我想通过某些列/属性“区分”集合,但又不丢弃其他列(是的,这的确会丢失信息,因为它会随心所欲地变成其他列的哪个值)。
请注意,此扩展功能不如采用IEqualityComparer<T>
的Distinct重载强大,因为此类操作可以执行更复杂的比较逻辑,但这只是我现在所需要的:)
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> getKeyFunc)
{
return from s in source
group s by getKeyFunc(s) into sourceGroups
select sourceGroups.First();
}
用法示例:
var items = new[]
{
new { A = 1, B = "foo", C = Guid.NewGuid(), },
new { A = 2, B = "foo", C = Guid.NewGuid(), },
new { A = 1, B = "bar", C = Guid.NewGuid(), },
new { A = 2, B = "bar", C = Guid.NewGuid(), },
};
var itemsByA = items.DistinctBy(item => item.A).ToList();
var itemsByB = items.DistinctBy(item => item.B).ToList();
最佳答案
干得好。我不认为这比您自己的版本要有效得多,但是应该有一点优势。它只需要对序列进行一次遍历,就可以对每一项进行yield
处理,而无需首先对整个序列进行分组。
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return source.DistinctBy(keySelector, null);
}
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
{
if (source == null)
throw new ArgumentNullException("source");
if (keySelector == null)
throw new ArgumentNullException("keySelector");
return source.DistinctByIterator(keySelector, keyComparer);
}
private static IEnumerable<TSource> DistinctByIterator<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
{
var keys = new HashSet<TKey>(keyComparer);
foreach (TSource item in source)
{
if (keys.Add(keySelector(item)))
yield return item;
}
}
关于c# - “更好的”(更简单,更快,什么)版本的“与众不同”?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3259816/