我讨厌发布此内容,因为它有点主观,但感觉有一种我没有想到的更好的方法来做到这一点。
有时我想通过某些列/属性来“区分”集合,但又不想丢弃其他列(是的,这确实会丢失信息,因为最终得到的其他列的值变得任意)。
请注意,此扩展的功能不如采用 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();
最佳答案
给你。我不认为这比你自己的版本更有效,但它应该有一点优势。它只需要一次通过序列,产生
每个项目,而不是需要首先对整个序列进行分组。
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# - "better"(更简单,更快,无论如何)版本'distinct by delegate'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3259816/